1、图片缩放:不解析整个图片信息。
public class DemoActivity extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); ImageView iv = (ImageView) this.findViewById(R.id.iv); // BitmapFactory.Options bmpFactoryOptions = new BitmapFactory.Options(); // //按1/8的大小加载到内存 // bmpFactoryOptions.inSampleSize = 8; // Bitmap bm = BitmapFactory.decodeFile("/sdcard/img.jpg",bmpFactoryOptions); // iv.setImageBitmap(bm); // //1. 首先得到屏幕的宽高 Display currentDisplay = getWindowManager().getDefaultDisplay(); int dw = currentDisplay.getWidth(); int dh = currentDisplay.getHeight(); // 2. 获取图片的宽度和高度 BitmapFactory.Options bmpFactoryOptions = new BitmapFactory.Options(); // 设置inJustDecodeBounds = true ,只会解析文件头信息; bmpFactoryOptions.inJustDecodeBounds = true; // 不会真正的解析这个位图 Bitmap bmp = BitmapFactory.decodeFile("/sdcard/img.jpg", bmpFactoryOptions); //得到图片的宽度和高度 int heightRatio = (int)Math.ceil(bmpFactoryOptions.outHeight/(float)dh); int widthRatio = (int)Math.ceil(bmpFactoryOptions.outWidth/(float)dw); Log.v("HEIGHTRATIO",""+heightRatio); Log.v("WIDTHRATIO",""+widthRatio); //真正的解析位图 bmpFactoryOptions.inJustDecodeBounds = false; if(heightRatio>widthRatio){ bmpFactoryOptions.inSampleSize = heightRatio; }else{ bmpFactoryOptions.inSampleSize = widthRatio; } bmp = BitmapFactory.decodeFile("/sdcard/img.jpg", bmpFactoryOptions); iv.setImageBitmap(bmp); } }
2、ExifInterface获取或设置图片的exif信息:
public class DemoActivity extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); try { ExifInterface exif = new ExifInterface("sdcard/img.jpg"); System.out.println( exif.getAttribute(ExifInterface.TAG_DATETIME)); System.out.println( exif.getAttribute(ExifInterface.TAG_IMAGE_LENGTH)); System.out.println( exif.getAttribute(ExifInterface.TAG_IMAGE_WIDTH)); exif.setAttribute("camera", "柯达相机"); System.out.println( exif.getAttribute("camera")); } catch (Exception e) { e.printStackTrace(); } } }
3、从图库里面选择一个图片,然后将它设置到ImageView。
public class DemoActivity extends Activity { ImageView iv; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); iv = (ImageView) this.findViewById(R.id.iv); } public void click(View view){ //选择图库意图,打开图库 Intent intent = new Intent(Intent.ACTION_PICK); intent.setType("image/*"); startActivityForResult(intent, 0); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { if(data!=null){ //图片的uri Uri uri = data.getData() ; iv.setImageURI(uri); } super.onActivityResult(requestCode, resultCode, data); } }
4、创建图片(bitmap)的拷贝:
public class DemoActivity extends Activity{ ImageView iv1; ImageView iv2; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); iv1= (ImageView) this.findViewById(R.id.iv1); iv2= (ImageView) this.findViewById(R.id.iv2); } public void click(View view){ Intent intent = new Intent(Intent.ACTION_PICK); intent.setType("image/*"); startActivityForResult(intent, 0); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { if(data!=null){ //图片的uri Uri uri = data.getData() ; iv1.setImageURI(uri); // 获取第一个图片 的拷贝 设置到iv2的控件里面 try { //通过uri获取一个流对象。getContentResolver().openInputStream(uri) Bitmap bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(uri)); //图片缩放 Matrix matrix = new Matrix(); // matrix.setValues(new float[] { // 2, 0, 0, // 0, 1, 0, // 0, 0, 1 // });//矩阵缩放 // matrix.setScale(1.5f, 1.0f);//水平方向为1.5倍,垂直方向不做改变 // matrix.postTranslate(bitmap.getWidth(), 1.0f);//与setScale可以实现图片翻转 // matrix.setRotate(30); //画笔 Paint paint = new Paint(); paint.setAntiAlias(true);//消除锯齿 matrix.setRotate(15);//图片旋转 //得到一个大小 配置跟原图一样的空白的位图 //Bitmap alterbitmap = Bitmap.createBitmap(bitmap.getWidth()*2, bitmap.getHeight(), bitmap.getConfig()); Bitmap alteredBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, false); //画布对象 Canvas canvas = new Canvas(); //将图片流bitmap应用到画布上 canvas.drawBitmap(bitmap, matrix, paint); iv2.setImageBitmap(alteredBitmap); } catch (Exception e) { e.printStackTrace(); } } super.onActivityResult(requestCode, resultCode, data); } }
最后一个:filter解释
true if the source should be filtered. Only applies if the matrix contains more than just translation.
当进行的不只是平移变换时,filter参数为true可以进行滤波处理,有助于改善新图像质量;flase时,计算机不做过滤处理。
图片裁剪,可用这个方法:
Bitmap source:要从中截图的原始位图
int x: 起始x坐标
int y:起始y坐标
int width: 要截的图的宽度
int height:要截的图的高度
要想imageView.setImageMatrix()方法起作用,xml得配置android:scaleType="matrix"
matrix.setRotate和matrix.postRotate的区别:
post...:平移、旋转等效果可以叠加在一起;
set...:前一种效果会消失,只有后来的操作,即它会重置Matrix
5、图片合成:
public class DemoActivity extends Activity { Bitmap basebitmap; Canvas canvas ; Paint paint; ImageView iv; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); iv = (ImageView) this.findViewById(R.id.iv); } public void select1(View view){ Intent intent = new Intent(Intent.ACTION_PICK); intent.setType("image/*"); startActivityForResult(intent, 10); // 从图库里面获取第一个图片 } public void save(View view){ File file = new File("/sdcard/1.jpg"); FileOutputStream fos; try { fos = new FileOutputStream(file); basebitmap.compress(CompressFormat.JPEG, 100, fos); //显示的发送一条广播 //sd卡挂载的广播 Intent intent = new Intent(Intent.ACTION_MEDIA_MOUNTED,Uri.parse("file://"+Environment.getExternalStorageDirectory())); sendBroadcast(intent); } catch (FileNotFoundException e) { e.printStackTrace(); } } public void select2(View view){ Intent intent = new Intent(Intent.ACTION_PICK); intent.setType("image/*"); startActivityForResult(intent, 20); // 从图库里面获取第一个图片 } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { if(requestCode==10){ if(data!=null){ Uri uri = data.getData(); try { Bitmap bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(uri)); basebitmap = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), bitmap.getConfig()); canvas = new Canvas(basebitmap); paint = new Paint(); canvas.drawBitmap(bitmap, 0, 0, paint); } catch (Exception e) { e.printStackTrace(); } } }else if(requestCode==20){ if(data!=null){ Uri uri = data.getData(); //把第二张位图的内容 画在 basebitmap上 try { Bitmap bitmap = BitmapFactory.decodeStream( getContentResolver().openInputStream(uri)); paint.setXfermode(new PorterDuffXfermode(android.graphics.PorterDuff.Mode.MULTIPLY)); canvas.drawBitmap(bitmap, 0,0, paint); iv.setImageBitmap(basebitmap); } catch (Exception e) { e.printStackTrace(); } } } super.onActivityResult(requestCode, resultCode, data); } }
6、根据路径Path绘制文字:
public class DemoActivity extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(new MyView(this)); } private class MyView extends View{ public MyView(Context context) { super(context); } @Override protected void onDraw(Canvas canvas) { Paint paint = new Paint(); paint.setColor(Color.GREEN); paint.setTextSize(20); paint.setTypeface(Typeface.DEFAULT); Path p = new Path(); p.moveTo(20, 20); p.lineTo(100, 150); p.lineTo(200, 220); canvas.drawTextOnPath("Hello this is text on a path", p, 0, 0, paint); super.onDraw(canvas); } } }
7、绘图(根据手指移动创建图片并保存):
public class DemoActivity extends Activity { ImageView iv; Bitmap bitmap; Canvas canvas; Paint paint; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); iv = (ImageView) this.findViewById(R.id.iv); Display diaplay = getWindow().getWindowManager().getDefaultDisplay(); int height = diaplay.getHeight() - 40; int width = diaplay.getWidth(); bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); iv.setImageBitmap(bitmap); canvas = new Canvas(bitmap); paint= new Paint(); paint.setColor(Color.GREEN); paint.setStrokeWidth(10); iv.setOnTouchListener(new OnTouchListener() { float startx = 0; float starty = 0; @Override public boolean onTouch(View v, MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: startx = event.getX(); starty = event.getY(); break; case MotionEvent.ACTION_MOVE: float x = event.getX(); float y = event.getY(); canvas.drawLine(startx, starty, x, y, paint); startx = event.getX(); starty = event.getY(); //通知imageview更新界面 iv.invalidate(); break; case MotionEvent.ACTION_UP: float endx = event.getX(); float endy = event.getY(); canvas.drawLine(startx, starty, endx, endy, paint); //通知imageview更新界面 iv.invalidate(); break; default: break; } return true; } }); } public void save(View view) { File file = new File("/sdcard/"+System.currentTimeMillis()+".jpg"); FileOutputStream fos; try { fos = new FileOutputStream(file); bitmap.compress(CompressFormat.JPEG, 100, fos); //显示的发送一条广播 //sd卡挂载的广播 Intent intent = new Intent(Intent.ACTION_MEDIA_MOUNTED,Uri.parse("file://"+Environment.getExternalStorageDirectory())); sendBroadcast(intent); } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
8、矩阵Matrix
Matrix的操作,总共分为translate(平移),rotate(旋转),scale(缩放)和skew(倾斜)四种,每一种变换在Android的API里都提供了set, post和pre三种操作方式,除了translate,其他三种操作都可以指定中心点。
set是直接设置Matrix的值,每次set一次,整个Matrix的数组都会变掉。
post是后乘,当前的矩阵乘以参数给出的矩阵。可以连续多次使用post,来完成所需的整个变换。
例如,要将一个图片旋转30度,然后平移到(100,100)的地方,那么可以这样做:
Matrix m = new Matrix(); m.postRotate(30 ); m.postTranslate(100 , 100 );
pre是前乘,参数给出的矩阵乘以当前的矩阵。所以操作是在当前矩阵的最前面发生的。例如上面的例子,如果用pre的话
Matrix m = new Matrix(); m.setTranslate(100 , 100 ); m.preRotate(30 )
旋转、缩放和倾斜都可以围绕一个中心点来进行,如果不指定,默认情况下,是围绕(0,0)点来进行。
public class MyView extends View { private Bitmap mBitmap; private Matrix mMatrix = new Matrix(); public MyView(Context context) { super (context); initialize(); } private void initialize() { Bitmap bmp = ((BitmapDrawable)getResources().getDrawable(R.drawable.show)).getBitmap(); mBitmap = bmp; /*首先,将缩放为100*100。这里scale的参数是比例。有一点要注意,如果直接用100/ bmp.getWidth()的话,会得到0,因为是整型相除,所以必须其中有一个是float型的,直接用100f就好。*/ mMatrix.setScale(100f/bmp.getWidth(), 100f/bmp.getHeight()); //平移到(100,100)处 mMatrix.postTranslate(100 , 100 ); //倾斜x和y轴,以(100,100)为中心。 mMatrix.postSkew(0 .2f, 0 .2f, 100 , 100 ); } @Override protected void onDraw(Canvas canvas) { // super.onDraw(canvas); //如果界面上还有其他元素需要绘制,只需要将这句话写上就行了。 canvas.drawBitmap(mBitmap, mMatrix, null ); } }
pre方法表示矩阵前乘,例如:变换矩阵为A,原始矩阵为B,pre方法的含义即是A*B post方法表示矩阵后乘,例如:变换矩阵为A,原始矩阵为B,post方法的含义即是B*A matrix.preScale(0.5f, 1); matrix.preTranslate(10, 0); matrix.postScale(0.7f, 1); matrix.postTranslate(15, 0); 等价于: translate(10, 0) -> scale(0.5f, 1) -> scale(0.7f, 1) -> translate(15, 0) 注意:后调用的pre操作先执行,而后调用的post操作则后执行。 set方法一旦调用即会清空之前matrix中的所有变换,例如: matrix.preScale(0.5f, 1); matrix.setScale(1, 0.6f); matrix.postScale(0.7f, 1); matrix.preTranslate(15, 0); 等价于 translate(15, 0) -> scale(1, 0.6f) -> scale(0.7f, 1) matrix.preScale (0.5f, 1)将不起作用。