图片

来源:互联网 发布:沙钢网络培训平台 编辑:程序博客网 时间:2024/05/16 01:43
1.从Gallery中获取图片
  Gallery是系统自带的相册,与之对应的Activity类是GalleryPicker。
  相册中图片列表对应一个Activity类ImageGallery。
  所有可以使用startActivityForResult方法跳转到该Activity,点击一张图片后获取返回数据。系统会返回图片的Uri。
  而自定义ImageView可以使用方法setImageURI(uri)就可以展示指定图片了。


2.获取位图bitmap
  
  1)从项目资源获取
  Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.a);

  2)从网络流获取
  // 获取输入流
  InputStream in = response.getEntity().getContent();
  // 将输入流转成Bitmap
  Bitmap bitmap = BitmapFactory.decodeStream(in);

  3)根据颜色矩阵创建图片
  Bitmap bitmap = Bitmap.createBitmap(int[] colors, width, heigth, Config config);
  //最后一个参数: Config.ARGB_8888或者其他

  4)从sd卡中加载图片
  Bitmap bitmap = BitmapFactory.decodeFile("/mnt/sdcard/a.jpg");

3.加载大图片内存溢出OOM
  2M的图片加载到内存需要30M内存

  1) 一般加载大图片到内存只加载原来的n分之一,比如八分之一

  代码:

  BitmapFactory.Options opts = new BitmapFactory.Options();  // 设置图片为原来的八分之一  opts.inSampleSize = 8;  Bitmap bitmap = BitmapFactory.decodeFile("/mnt/sdcard/big.jpg", opts);  iv.setImageBitmap(bitmap);

 2) 根据当前屏幕分辨率的大小,按比例加载图片
  代码:

BitmapFactory.Options opts = new BitmapFactory.Options();// 设置不获取图片本身,只获取图片的属性opts.inJustDecodeBounds = true;BitmapFactory.decodeFile("/mnt/sdcard/mm.jpg", opts);// 获取图片的宽高int width = opts.outWidth;int height = opts.outHeight;System.out.println("图片的宽和高:" + width + " --- " + height);// 获取屏幕的宽高Display display = getWindowManager().getDefaultDisplay();int sw = display.getWidth();int sh = display.getHeight();System.out.println("屏幕的宽和高:" + sw + " --- " + sh);// 得到图片宽高和屏幕宽高的比例// ceil -- 向上取整int widthRatio = (int) Math.ceil(width / (float) sw);int heightRatio = (int) Math.ceil(height / (float) sh);Log.v("WIDTHRATIO", widthRatio + "");Log.v("HEIGHTRATIO", heightRatio + "");// 如果图片的宽高大于屏幕宽高,那么按宽高变化大的进行缩放if (widthRatio > 1 && heightRatio > 1) {// 将比例大的设置为缩放因子opts.inSampleSize = widthRatio > heightRatio ? widthRatio: heightRatio;}// 重新设置opts为获取图片opts.inJustDecodeBounds = false;// 加载图片Bitmap bitmap = BitmapFactory.decodeFile("/mnt/sdcard/mm.jpg", opts);iv.setImageBitmap(bitmap);

4.图片涂鸦
  核心代码:

1) ImageView.setOnTouchListener(listener); 给ImageView设置触摸事件,注意监听器的onTouch方法返回值是true,表示消费掉事件,不再传递。在onTouch方法中,进行涂鸦绘制。

iv.setOnTouchListener(new OnTouchListener() {@Overridepublic boolean onTouch(View v, MotionEvent event) {// 绘制开始位置int startX = 0;int startY = 0;switch (event.getAction()) {// 按下case MotionEvent.ACTION_DOWN:// 记录开始位置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.setImageBitmap(bit);// 将结束位置设置为新的起始位置startX = stopX;startY = stopY;break;// 抬起case MotionEvent.ACTION_UP:break;default:break;}// 返回true,消费了本次事件,不再向下传递return true;}});

2) 创建Canvas,传入的Bitmap一定是新创建的而不是加载的图片,即不能再原图片上绘制。

     //加载图片     Bitmap bitmap = BitmapFactory.decodeFile("/mnt/sdcard/mm.jpg", opts);     // 根据原图重新创建一张图片     Bitmap bit = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(),bitmap.getConfig());     //创建画布,将新图片作为参数传递到画布     //一定要注意不要使用原图,否则抛出异常     Canvas canvas = new Canvas(bit);     //绘制新图片     canvas.drawBitmap(bitmap, new Matrix(), paint);

总代码:

public class MainActivity extends Activity {private ImageView iv;// 加载的原图private Bitmap bitmap;// 根据原图绘制的新图private Bitmap bit;private Canvas canvas;private Paint paint;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);iv = (ImageView) findViewById(R.id.iv);// 加载图片bitmap = BitmapFactory.decodeFile("/mnt/sdcard/mm.jpg");// 画布与画笔// 根据原图重新创建一张图片bit = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(),bitmap.getConfig());// 创建画布,将新图片作为参数传递到画布// 一定要注意不要使用原图,否则抛出异常canvas = new Canvas(bit);// 画笔paint = new Paint();// 把原图内容绘制到新图片canvas.drawBitmap(bitmap, new Matrix(), paint);// 将新图片设置到ImageViewiv.setImageBitmap(bit);// 设置监听iv.setOnTouchListener(new OnTouchListener() {// 绘制开始位置int startX;int startY;@Overridepublic boolean onTouch(View v, MotionEvent event) {switch (event.getAction()) {// 按下case MotionEvent.ACTION_DOWN:// 记录开始位置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.setImageBitmap(bit);// 将结束位置设置为新的起始位置startX = stopX;startY = stopY;break;// 抬起case MotionEvent.ACTION_UP:break;default:break;}// 返回true,消费了本次事件,不再向下传递return true;}});}}

5.图片加水印并保存
  加水印:
  核心代码:canvas.drawText(String text, float x, float y, Paint paint);
            参数:内容,起始x,起始y,画笔。
  注意:同样需要根据原图新创建一张图片。

  保存:
  核心代码:bitmap.compress (Bitmap.CompressFormat format, int quality, OutputStream stream)


6. 改变图片的rgba
   安卓把颜色通过4*5的颜色矩阵进行处理。
   核心类:ColorFilter ColorMatirx
   核心代码:paint.setColorFilter(filter);

   开发时使用其子类 --- ColorMatrixColorFilter
   ColorMatrixColorFilter filter = new ColorMatrixColorFilter(ColorMatrix matrix);
   创建ColorMatrixColorFilter实例时需要一个参数:ColorMatrix
   ColorMatrix matrix = new ColorMatrix();
   //设置一个4*5数组
   matrix.set(new float[]{
1,0,0,0,0, //r
0,1,0,0,0, //g
0,0,1,0,0, //b
0,0,0,1,0  //a
   });

代码:

        // 加载图片Bitmap bitmap = BitmapFactory.decodeFile("/mnt/sdcard/mm.jpg");// 根据原图创建新图片Bitmap bm = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(),bitmap.getConfig());Canvas canvas = new Canvas(bm);Paint paint = new Paint();//改变图片的rgbaColorMatrix matrix = new ColorMatrix();matrix.set(new float[]{1,0,0,0,0, //r0,1,0,0,0, //g0,0,1,0,0, //b0,0,0,0.3f,0  //a});ColorMatrixColorFilter filter = new ColorMatrixColorFilter(matrix);//rgba核心代码 --- 设置画笔的颜色过滤器paint.setColorFilter(filter);// 绘制新图片canvas.drawBitmap(bitmap, new Matrix(), paint);iv.setImageBitmap(bm);


改变图片rgba总代码:

public class MainActivity extends Activity {private SeekBar sbR;private SeekBar sbG;private SeekBar sbB;private SeekBar sbA;private ImageView iv;private Bitmap bitmap;private Bitmap bm;private Canvas canvas;private Paint paint;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);sbR = (SeekBar) findViewById(R.id.sb_r);sbG = (SeekBar) findViewById(R.id.sb_g);sbB = (SeekBar) findViewById(R.id.sb_b);sbA = (SeekBar) findViewById(R.id.sb_a);iv = (ImageView) findViewById(R.id.iv);// 加载图片bitmap = BitmapFactory.decodeFile("/mnt/sdcard/mm.jpg");bm = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(),bitmap.getConfig());canvas = new Canvas(bm);paint = new Paint();// 绘制新图片canvas.drawBitmap(bitmap, new Matrix(), paint);iv.setImageBitmap(bm);// 改变图片红色显示sbR.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {@Overridepublic void onStopTrackingTouch(SeekBar seekBar) {}@Overridepublic void onStartTrackingTouch(SeekBar seekBar) {}@Overridepublic void onProgressChanged(SeekBar seekBar, int progress,boolean fromUser) {// 根据progress计算比例float rate = (float) (255 - progress) / 255;ColorMatrix matrix = new ColorMatrix();matrix.set(new float[] { rate, 0, 0, 0, 0, // r0, 1, 0, 0, 0, // g0, 0, 1, 0, 0, // b0, 0, 0, 1, 0 // a});ColorMatrixColorFilter filter = new ColorMatrixColorFilter(matrix);// rgba核心代码 --- 设置画笔的颜色过滤器paint.setColorFilter(filter);// 绘制新图片canvas.drawBitmap(bitmap, new Matrix(), paint);iv.setImageBitmap(bm);}});// 改变图片绿色显示sbG.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {@Overridepublic void onStopTrackingTouch(SeekBar seekBar) {}@Overridepublic void onStartTrackingTouch(SeekBar seekBar) {}@Overridepublic void onProgressChanged(SeekBar seekBar, int progress,boolean fromUser) {// 根据progress计算比例float rate = (float) (255 - progress) / 255;ColorMatrix matrix = new ColorMatrix();matrix.set(new float[] { 1, 0, 0, 0, 0, // r0, rate, 0, 0, 0, // g0, 0, 1, 0, 0, // b0, 0, 0, 1, 0 // a});ColorMatrixColorFilter filter = new ColorMatrixColorFilter(matrix);// rgba核心代码 --- 设置画笔的颜色过滤器paint.setColorFilter(filter);// 绘制新图片canvas.drawBitmap(bitmap, new Matrix(), paint);iv.setImageBitmap(bm);}});// 改变图片蓝色显示sbB.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {@Overridepublic void onStopTrackingTouch(SeekBar seekBar) {}@Overridepublic void onStartTrackingTouch(SeekBar seekBar) {}@Overridepublic void onProgressChanged(SeekBar seekBar, int progress,boolean fromUser) {// 根据progress计算比例float rate = (float) (255 - progress) / 255;ColorMatrix matrix = new ColorMatrix();matrix.set(new float[] { 1, 0, 0, 0, 0, // r0, 1, 0, 0, 0, // g0, 0, rate, 0, 0, // b0, 0, 0, 1, 0 // a});ColorMatrixColorFilter filter = new ColorMatrixColorFilter(matrix);// rgba核心代码 --- 设置画笔的颜色过滤器paint.setColorFilter(filter);// 绘制新图片canvas.drawBitmap(bitmap, new Matrix(), paint);iv.setImageBitmap(bm);}});// 改变图片透明度sbA.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {@Overridepublic void onStopTrackingTouch(SeekBar seekBar) {}@Overridepublic void onStartTrackingTouch(SeekBar seekBar) {}@Overridepublic void onProgressChanged(SeekBar seekBar, int progress,boolean fromUser) {// 根据progress计算比例float rate = (float) (255 - progress) / 255;ColorMatrix matrix = new ColorMatrix();matrix.set(new float[] { 1, 0, 0, 0, 0, // r0, 1, 0, 0, 0, // g0, 0, 1, 0, 0, // b0, 0, 0, rate, 0 // a});ColorMatrixColorFilter filter = new ColorMatrixColorFilter(matrix);// rgba核心代码 --- 设置画笔的颜色过滤器paint.setColorFilter(filter);// 绘制新图片canvas.drawBitmap(bitmap, new Matrix(), paint);iv.setImageBitmap(bm);}});}}


7.设置图片为黑白效果
  核心代码:
  paint.setColorFilter(filter);

//颜色矩阵 --- ColorMatrix
  matrix.setSaturation(0);

总代码:

        bitmap = BitmapFactory.decodeFile("/mnt/sdcard/mm.jpg");// 画布与画笔// 根据原图重新创建一张图片bit = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(),bitmap.getConfig());// 创建画布,将新图片作为参数传递到画布// 一定要注意不要使用原图,否则抛出异常canvas = new Canvas(bit);// 画笔paint = new Paint();// 设置成黑白效果ColorMatrix matrix = new ColorMatrix();// 核心代码matrix.setSaturation(0);ColorMatrixColorFilter filter = new ColorMatrixColorFilter(matrix);paint.setColorFilter(filter);// 把原图内容绘制到新图片canvas.drawBitmap(bitmap, new Matrix(), paint);// 将新图片设置到ImageViewiv.setImageBitmap(bit);

8.图片的缩放
  安卓中使用3*3的矩阵对图片进行处理。
  核心类:Matrix
  核心代码:matrix.setScale(float sx, float sy)
  例:
  // 使用矩阵进行缩放
  Matrix matrix = new Matrix();
  // 宽为原图2倍,高为原图2分之1
  matrix.setScale(2.0f, 0.5f);

  canvas.drawBitmap(bitmap, matrix, paint);

  代码:

  布局xml

<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent" >    <LinearLayout        android:layout_width="match_parent"        android:layout_height="match_parent"        android:orientation="vertical" >        <ImageView            android:id="@+id/iv1"            android:layout_width="wrap_content"            android:layout_height="wrap_content" />        <ImageView            android:id="@+id/iv2"            android:layout_width="wrap_content"            android:layout_height="wrap_content" />    </LinearLayout></ScrollView>

MainActivity

public class MainActivity extends Activity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);ImageView iv1 = (ImageView) findViewById(R.id.iv1);ImageView iv2 = (ImageView) findViewById(R.id.iv2);// 加载图片Bitmap bitmap = BitmapFactory.decodeFile("/mnt/sdcard/mm.jpg");// 根据原图片创建新图片// 宽是原图2倍,高是原图2分之1Bitmap bm = Bitmap.createBitmap(bitmap.getWidth() * 2,bitmap.getHeight() / 2, bitmap.getConfig());Canvas canvas = new Canvas(bm);// 使用矩阵进行缩放Matrix matrix = new Matrix();// 宽为原图2倍,高为原图2分之1matrix.setScale(2.0f, 0.5f);Paint paint = new Paint();canvas.drawBitmap(bitmap, matrix, paint);iv1.setImageBitmap(bitmap);iv2.setImageBitmap(bm);}}

9.图片的旋转
    核心类:Matrix
    核心方法:

   1)
    matrix.setRotate(float degrees)
    matrix.setRotate(float degrees, float px, float py)
    围绕点px, py 旋转 degrees度, 如果没设置坐标,默认以0,0点旋转.
    例:
    matrix.setRotate(90, 180, 120);

    2)
    matrix.postRotate(float degrees)
    matrix.postRotate(float degrees, float px, float py)


10.图片平移
    核心类:Matrix
    核心方法:matrix.setTranslate(float dx, float dy)
              matrix.postTranslate(float dx, float dy)
    例:matrix.setTranslate(100, 100)  //100px


11.镜面效果 --- 翻转
   翻转实际使用图片的缩放,即matrix.setScale();
   镜面效果原理是先将图片沿y轴线翻转,然后再平移回去。
   核心代码:
        // 先将图片沿y轴翻转
matrix.setScale(-1f, 1f);
// 再将图片平移回来
matrix.postTranslate(bitmap.getWidth(), 0);


12.倒影效果 --- 将y坐标沿x轴翻转
   倒影效果原理是先将图片沿x轴线翻转,然后再平移回去。
   核心代码:
        // 先将图片沿x轴翻转
matrix.setScale(1f, -1f);
// 再将图片平移回来
matrix.postTranslate(0, bitmap.getHeight());

// 加载图片Bitmap bitmap = BitmapFactory.decodeFile("/mnt/sdcard/mm.jpg");// 根据原图片创建新图片Bitmap bm = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(),bitmap.getConfig());Canvas canvas = new Canvas(bm);// 使用矩阵实现镜面效果Matrix matrix = new Matrix();// 1.缩放// matrix.setScale(2.0f, 0.5f);// 2.旋转// matrix.setRotate(45, 200, 180);// 3.平移// matrix.setTranslate(100, 100);// 4.镜面效果/*// 先将图片沿y轴翻转matrix.setScale(-1f, 1f);// 再将图片平移回来matrix.postTranslate(bitmap.getWidth(), 0);*/// 5.倒影效果// 先将图片沿x轴翻转matrix.setScale(1f, -1f);// 再将图片平移回来matrix.postTranslate(0, bitmap.getHeight());Paint paint = new Paint();canvas.drawBitmap(bitmap, matrix, paint);iv1.setImageBitmap(bitmap);iv2.setImageBitmap(bm);

13.Matrix的setXxx()方法和postXxx()方法的区别
   Matrix中带有pre, post的函数需要考虑先后顺序
   其实Matrix方法中的setXxx()方法会先清除该矩阵,即设为单位矩阵。之后设置其他操作的,所以是不能叠加各种效果在一起。
   所以,如果是想多种效果同时使用的话,用postRotate(), postTranslate()等类似的矩阵变换方法。


14.小结
  1) 与图片内容相关:比如涂鸦、水印,使用Canvas --- drawXXX(...) : canvas.drawLine(...) canvas.drawText(...)
  2) 与图片颜色相关:rgba,使用Paint/ColorFilter/ColorMatrix
  3) 与图片位置相关:平移、缩放、旋转等,使用Matrix



15.获得图片的像素矩阵 
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.a);
//像素数组
int[] pixels = new int[bitmap.getWidth() * bitmap.getHeigth()];
bitmap.getPixels(pixels, offset, stride, x, y, width, height);



0 0
原创粉丝点击