android 呼叫系統相機進行拍照及照片的裁切
阿新 • • 發佈:2019-01-23
呼叫系統相機進行拍照是android開發中常用到的功能,例如:拍照了直接發朋友圈等。還有常用的要進行圖片的裁剪,例如:上傳自己的頭像等。你又不能拍完照直接上傳,然後在讀取截止中間的,這樣不一定是使用者想要的部分。所以,我們通常是讓使用者自己按照我們的比例,來進行裁剪。這就要用到裁剪技術了。
今天,就是要說一下呼叫系統的相機的一些常用的技術。
一、呼叫系統的相機
//呼叫系統相機 Intent intent=new Intent(MediaStore.ACTION_IMAGE_CAPTURE); startActivityForResult(intent,SMALL_CAMERA)
呼叫這個程式碼之後,系統就會自動呼叫在清單檔案裡配置
清單了的配置如下:
<intent-filter > <action android:name="android.media.action.IMAGE_CAPTURE"/> <category android:name="android.intent.category.DEFAULT"/> </intent-filter>
二、獲取拍照的圖片通常有兩種方式:
1.直接獲取,不需要存到本地
//如果圖太大會造成記憶體溢位(OOM),取出的圖片系統會預設壓縮2.先把圖片存到本地,然後可以獲取到原圖,自己也可以控制壓縮多少,一般的專案都用這種方式Bundle bundle = data.getExtras(); Bitmap bitmap = (Bitmap) bundle.get("data"); iv.setImageBitmap(bitmap);
btn_original.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { //先驗證手機是否有sdcard String status= Environment.getExternalStorageStateonActivityResult裡的程式碼是:(); if(!status.equals(Environment.MEDIA_MOUNTED)) { Toast.makeText(getApplicationContext(),"你的sd卡不可用。",Toast.LENGTH_SHORT).show(); return; } filePath=Environment.getExternalStorageDirectory().getPath()+"/temp/"; File fileDir=new File(filePath); if(!fileDir.exists()) { fileDir.mkdirs(); } file=new File(filePath,temp); if (!file.exists()) { try { file.createNewFile(); } catch (IOException e) { e.printStackTrace(); } } Uri uri = Uri.fromFile(file); //呼叫系統相機 Intent intent=new Intent(MediaStore.ACTION_IMAGE_CAPTURE); intent.putExtra(MediaStore.EXTRA_OUTPUT,uri); startActivityForResult(intent,ORIGINAL_CAMERA); } });
//這種方法是通過記憶體卡的路徑進行讀取圖片,獲取的是原圖 FileInputStream fis = null; try { //把圖片轉化為位元組流 fis = new FileInputStream(file); //把流轉化圖片 Bitmap bitmapOriginal = BitmapFactory.decodeStream(fis); iv.setImageBitmap(bitmapOriginal); } catch (FileNotFoundException e) { e.printStackTrace(); }finally{ try { if(fis!=null) fis.close();//關閉流 } catch (IOException e) { e.printStackTrace(); } }三、把拍照的照片根據比例或大小進行裁切
btn_square.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { //先驗證手機是否有sdcard String status= Environment.getExternalStorageState(); if(!status.equals(Environment.MEDIA_MOUNTED)) { Toast.makeText(getApplicationContext(),"你的sd卡不可用。",Toast.LENGTH_SHORT).show(); return; } filePath=Environment.getExternalStorageDirectory().getPath()+"/temp/"; File fileDir=new File(filePath); if(!fileDir.exists()) { fileDir.mkdirs(); } file=new File(filePath,temp); if (!file.exists()) { try { file.createNewFile(); } catch (IOException e) { e.printStackTrace(); } } Uri uri = Uri.fromFile(file); Intent intent=new Intent(MediaStore.ACTION_IMAGE_CAPTURE); intent.putExtra(MediaStore.EXTRA_OUTPUT,uri); startActivityForResult(intent,SQUARE_CAMERA_PRE); } });
onActivityResult裡的程式碼是:
//跳到擷取圖片 case SQUARE_CAMERA_PRE: fileTemp=new File(filePath,picTemp); if (!fileTemp.exists()) { try { file.createNewFile(); } catch (IOException e) { e.printStackTrace(); } } Intent intent = new Intent("com.android.camera.action.CROP"); intent.setDataAndType(Uri.fromFile(file), "image/*");//要裁切的圖片源 intent.putExtra("crop", "true");//是否要裁切 // aspectX aspectY 是裁剪框寬高的比例 intent.putExtra("aspectX", 1); intent.putExtra("aspectY", 1); intent.putExtra("scale", true);// 去黑邊 // outputX outputY 是裁剪後生成圖片的寬高 // intent.putExtra("outputX", 800); // intent.putExtra("outputY", 800); intent.putExtra("scaleUpIfNeeded", true);// 去黑邊 intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());//返回圖片的格式 intent.putExtra("noFaceDetection", true); // return-data為true時,會直接返回bitmap資料,推薦下面為false時的方式,同上面的 // return-data為false時,不會返回bitmap,但需要指定一個MediaStore.EXTRA_OUTPUT儲存圖片uri intent.putExtra("return-data", false); intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(fileTemp)); startActivityForResult(intent, SQUARE_CAMERA); break; //獲取擷取的圖片 case SQUARE_CAMERA: //這種方法是通過記憶體卡的路徑進行讀取圖片,獲取的是原圖 FileInputStream fisSquare = null; try { //把圖片轉化為位元組流 fisSquare = new FileInputStream(fileTemp); //把流轉化圖片 Bitmap bitmapOriginal = BitmapFactory.decodeStream(fisSquare); iv.setImageBitmap(bitmapOriginal); } catch (FileNotFoundException e) { e.printStackTrace(); }finally{ try { if(fisSquare!=null) fisSquare.close();//關閉流 } catch (IOException e) { e.printStackTrace(); } } break;
不要忘了加上一個訪問sd許可權:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
最後放上activity的程式碼:
package com.sunshanglei.camera.system; import android.content.Intent; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.net.Uri; import android.os.Environment; import android.provider.MediaStore; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.ImageView; import android.widget.Toast; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; /** * use 呼叫系統相機 * author 孫尚磊 * create time 2017-4-22 */ public class MainActivity extends AppCompatActivity { private Button btn_original,btn_small,btn_square; private static final int SMALL_CAMERA=1;//壓縮圖請求碼 private static final int ORIGINAL_CAMERA=2;//原圖請求碼 private static final int SQUARE_CAMERA_PRE=3;//跳到正方形請求碼 private static final int SQUARE_CAMERA=4;//正方形請求碼 private ImageView iv; private String pathTemp,filePath; private File file,fileTemp; private String temp="temp.png",picTemp="picTemp.png"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); btn_original= (Button) findViewById(R.id.btn_original); btn_small= (Button) findViewById(R.id.btn_small); btn_square= (Button) findViewById(R.id.btn_square); iv= (ImageView) findViewById(R.id.iv); btn_original.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { //先驗證手機是否有sdcard String status= Environment.getExternalStorageState(); if(!status.equals(Environment.MEDIA_MOUNTED)) { Toast.makeText(getApplicationContext(),"你的sd卡不可用。",Toast.LENGTH_SHORT).show(); return; } filePath=Environment.getExternalStorageDirectory().getPath()+"/temp/"; File fileDir=new File(filePath); if(!fileDir.exists()) { fileDir.mkdirs(); } file=new File(filePath,temp); if (!file.exists()) { try { file.createNewFile(); } catch (IOException e) { e.printStackTrace(); } } Uri uri = Uri.fromFile(file); //呼叫系統相機 Intent intent=new Intent(MediaStore.ACTION_IMAGE_CAPTURE); intent.putExtra(MediaStore.EXTRA_OUTPUT,uri); startActivityForResult(intent,ORIGINAL_CAMERA); } }); btn_small.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { //呼叫系統相機 Intent intent=new Intent(MediaStore.ACTION_IMAGE_CAPTURE); startActivityForResult(intent,SMALL_CAMERA); } }); btn_square.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { //先驗證手機是否有sdcard String status= Environment.getExternalStorageState(); if(!status.equals(Environment.MEDIA_MOUNTED)) { Toast.makeText(getApplicationContext(),"你的sd卡不可用。",Toast.LENGTH_SHORT).show(); return; } filePath=Environment.getExternalStorageDirectory().getPath()+"/temp/"; File fileDir=new File(filePath); if(!fileDir.exists()) { fileDir.mkdirs(); } file=new File(filePath,temp); if (!file.exists()) { try { file.createNewFile(); } catch (IOException e) { e.printStackTrace(); } } Uri uri = Uri.fromFile(file); Intent intent=new Intent(MediaStore.ACTION_IMAGE_CAPTURE); intent.putExtra(MediaStore.EXTRA_OUTPUT,uri); startActivityForResult(intent,SQUARE_CAMERA_PRE); } }); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if(resultCode==RESULT_OK){ switch (requestCode){ //返回壓縮的圖片 case SMALL_CAMERA: if(data==null){ return; } //如果圖太大會造成記憶體溢位(OOM),取出的圖片系統會預設壓縮 Bundle bundle = data.getExtras(); Bitmap bitmap = (Bitmap) bundle.get("data"); iv.setImageBitmap(bitmap); break; //返回原圖 case ORIGINAL_CAMERA: //這種方法是通過記憶體卡的路徑進行讀取圖片,獲取的是原圖 FileInputStream fis = null; try { //把圖片轉化為位元組流 fis = new FileInputStream(file); //把流轉化圖片 Bitmap bitmapOriginal = BitmapFactory.decodeStream(fis); iv.setImageBitmap(bitmapOriginal); } catch (FileNotFoundException e) { e.printStackTrace(); }finally{ try { if(fis!=null) fis.close();//關閉流 } catch (IOException e) { e.printStackTrace(); } } break; //跳到擷取圖片 case SQUARE_CAMERA_PRE: fileTemp=new File(filePath,picTemp); if (!fileTemp.exists()) { try { file.createNewFile(); } catch (IOException e) { e.printStackTrace(); } } Intent intent = new Intent("com.android.camera.action.CROP"); intent.setDataAndType(Uri.fromFile(file), "image/*");//要裁切的圖片源 intent.putExtra("crop", "true");//是否要裁切 // aspectX aspectY 是裁剪框寬高的比例 intent.putExtra("aspectX", 1); intent.putExtra("aspectY", 1); intent.putExtra("scale", true);// 去黑邊 // outputX outputY 是裁剪後生成圖片的寬高 // intent.putExtra("outputX", 800); // intent.putExtra("outputY", 800); intent.putExtra("scaleUpIfNeeded", true);// 去黑邊 intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());//返回圖片的格式 intent.putExtra("noFaceDetection", true); // return-data為true時,會直接返回bitmap資料,推薦下面為false時的方式,同上面的 // return-data為false時,不會返回bitmap,但需要指定一個MediaStore.EXTRA_OUTPUT儲存圖片uri intent.putExtra("return-data", false); intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(fileTemp)); startActivityForResult(intent, SQUARE_CAMERA); break; //獲取擷取的圖片 case SQUARE_CAMERA: //這種方法是通過記憶體卡的路徑進行讀取圖片,獲取的是原圖 FileInputStream fisSquare = null; try { //把圖片轉化為位元組流 fisSquare = new FileInputStream(fileTemp); //把流轉化圖片 Bitmap bitmapOriginal = BitmapFactory.decodeStream(fisSquare); iv.setImageBitmap(bitmapOriginal); } catch (FileNotFoundException e) { e.printStackTrace(); }finally{ try { if(fisSquare!=null) fisSquare.close();//關閉流 } catch (IOException e) { e.printStackTrace(); } } break; } } } }
佈局檔案:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center_horizontal" android:orientation="vertical"> <Button android:id="@+id/btn_small" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="呼叫系統相機_獲取壓縮圖"/> <Button android:id="@+id/btn_original" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="呼叫系統相機_獲取原圖"/> <Button android:id="@+id/btn_square" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="呼叫系統相機_裁切寬高1:1"/> <ImageView android:id="@+id/iv" android:layout_width="200dp" android:layout_height="wrap_content" /> </LinearLayout>
效果圖: