顯示具有 Camera 標籤的文章。 顯示所有文章
顯示具有 Camera 標籤的文章。 顯示所有文章

2015年4月28日 星期二

Android Load Image From Camera Or Gallery 讀取照片從相機或圖片庫

利用相機拍照或從已經存在的圖片庫,讀取照片並紀錄,將其顯示在app上。
1.AndroidManifest.xml加入讀取與寫入權限
 
 
2./res/layout/activity_main.xml


    

        
    

    

        
        
    


3.MainActivity.java
package tw.android;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
import android.provider.MediaStore.MediaColumns;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageView;

public class MainActivity extends Activity {

 private Button btnSelect;
 private ImageView ivImage;

 private int REQUEST_CAMERA = 0, SELECT_FILE = 1;
 private String selectedImagePath; // 圖片檔案位置

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  btnSelect = (Button) findViewById(R.id.btnSelectPhoto);
  ivImage = (ImageView) findViewById(R.id.ivImage);

  // 取出最後圖片檔案位置
  try {
   SharedPreferences preferencesGet = getApplicationContext()
     .getSharedPreferences("image",
       android.content.Context.MODE_PRIVATE);
   selectedImagePath = preferencesGet.getString("selectedImagePath",
     ""); // 圖片檔案位置,預設為空

   Log.i("selectedImagePath", selectedImagePath + "");

  } catch (Exception e) {
  }

  /* 選擇照片 */
  btnSelect.setOnClickListener(new OnClickListener() {

   public void onClick(View v) {
    selectImage();
   }
  });

  setImage();
 }

 /* 設定圖片 */
 private void setImage() {
  BitmapFactory.Options options = new BitmapFactory.Options();
  options.inJustDecodeBounds = false; // 不顯示照片
  BitmapFactory.decodeFile(selectedImagePath, options);
  final int REQUIRED_SIZE = 200;
  int scale = 1;
  /* 圖片縮小2倍 */
  while (options.outWidth / scale / 2 >= REQUIRED_SIZE
    && options.outHeight / scale / 2 >= REQUIRED_SIZE) {
   scale *= 2;
  }
  options.inSampleSize = scale;
  options.inJustDecodeBounds = false; // 顯示照片
  Bitmap bm = BitmapFactory.decodeFile(selectedImagePath, options);
  Log.i("selectedImagePath", selectedImagePath + "");
  ivImage.setImageBitmap(bm);// 將圖片顯示
 }

 private void selectImage() {
  final String item1, item2, item3;
  item1 = "拍一張照";
  item2 = "從圖庫選取";
  item3 = "取消";

  final CharSequence[] items = { item1, item2, item3 };

  AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
  builder.setTitle("新增照片視窗");
  builder.setItems(items, new DialogInterface.OnClickListener() {
   public void onClick(DialogInterface dialog, int item) {
    switch (item) {
    case 0: // 拍一張照
     Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
     startActivityForResult(intent, REQUEST_CAMERA);
     break;
    case 1: // 從圖庫選取
     Intent intent1 = new Intent(
       Intent.ACTION_PICK,
       android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
     intent1.setType("image/*");
     startActivityForResult(
       Intent.createChooser(intent1, "選擇開啟圖庫"),
       SELECT_FILE);
     break;
    default: // 取消
     dialog.dismiss(); // 關閉對畫框
     break;
    }

   }
  });
  builder.show();
 }

 /* 啟動選擇方式 */
 @Override
 public void onActivityResult(int requestCode, int resultCode, Intent data) {
  super.onActivityResult(requestCode, resultCode, data);

  if (resultCode == Activity.RESULT_OK) {
   if (requestCode == SELECT_FILE) // 從圖庫開啟
    onSelectFromGalleryResult(data);
   else if (requestCode == REQUEST_CAMERA) // 拍照
    onCaptureImageResult(data);
  }
 }

 /* 拍照 */
 private void onCaptureImageResult(Intent data) {
  Bitmap thumbnail = (Bitmap) data.getExtras().get("data");
  ByteArrayOutputStream bytes = new ByteArrayOutputStream();
  thumbnail.compress(Bitmap.CompressFormat.JPEG, 90, bytes);
  File destination = new File(Environment.getExternalStorageDirectory(),
    System.currentTimeMillis() + ".jpg"); // 輸出檔案名稱
  selectedImagePath = destination + ""; // 輸出檔案位置
  FileOutputStream fo;
  try {
   destination.createNewFile(); // 建立檔案
   fo = new FileOutputStream(destination); // 輸出
   fo.write(bytes.toByteArray());
   fo.close();
  } catch (FileNotFoundException e) {
   e.printStackTrace();
  } catch (IOException e) {
   e.printStackTrace();
  }

  ivImage.setImageBitmap(thumbnail); // 將圖片顯示
 }

 @SuppressWarnings("deprecation")
 private void onSelectFromGalleryResult(Intent data) {
  Uri selectedImageUri = data.getData();
  String[] projection = { MediaColumns.DATA };
  Cursor cursor = managedQuery(selectedImageUri, projection, null, null,
    null);
  int column_index = cursor.getColumnIndexOrThrow(MediaColumns.DATA);
  cursor.moveToFirst();

  selectedImagePath = cursor.getString(column_index); // 選擇的照片位置

  setImage(); // 設定圖片
 }

 /* 結束時 */
 @Override
 protected void onDestroy() {
  super.onDestroy();
  /* 紀錄圖片檔案位置 */
  SharedPreferences preferencesSave = getApplicationContext()
    .getSharedPreferences("image",
      android.content.Context.MODE_PRIVATE);
  SharedPreferences.Editor editor = preferencesSave.edit();
  editor.putString("selectedImagePath", selectedImagePath); // 紀錄最後圖片位置
  editor.commit();

  Log.i("onDestroy", "onDestroy");
 }

}



檔案下載:
https://github.com/terryyamg/loadImageFromGalleryTest
參考來源:
http://www.theappguruz.com/blog/android-take-photo-camera-gallery-code-sample/

2014年12月24日 星期三

Android Camera AutoFocus list delete picture 拍照 自動對焦 列出照片 刪除照片

拍照功能參考在 Android 裡使用 Camera 照相
並加入自動對焦與列出照片並可刪除該照片檔案

1.AndroidManifest.xml加入權限


    

    
    

    
        
            
                

                
            
        
        
        
        
        
    


2.建立java檔與layout檔

TakeAPhotoActivity.java 拍照
package tw.android;

import android.app.Activity;
import android.content.Intent;
import android.hardware.Camera;
import android.hardware.Camera.AutoFocusCallback;
import android.os.Bundle;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.widget.Button;

public class TakeAPhotoActivity extends Activity {

 private static final String TAG = "TakeAPhotoActivity";
 private SurfaceView sv;
 // private ImageView iv;
 private Button takePhotoBtn, hidePhotoBtn, autoFocus,picList;
 // 相機 callback
 private CameraCallback cc;
 // 快門 callback
 private ShCallback sc;
 // 處理 raw data callback
 private RawCallback rc;
 // 處理 jpg callback
 private JpgCallback jc;

 @Override
 public void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.take_a_photo_activity);

  this.sv = (SurfaceView) this.findViewById(R.id.sv);
  this.takePhotoBtn = (Button) this.findViewById(R.id.takePhotoBtn);
  this.hidePhotoBtn = (Button) this.findViewById(R.id.hidePhotoBtn);
  this.autoFocus = (Button) this.findViewById(R.id.autoFocus);
  this.picList= (Button) this.findViewById(R.id.picList);
  
  this.cc = new CameraCallback();
  this.sc = new ShCallback();
  this.rc = new RawCallback();
  this.jc = new JpgCallback(this);

  Log.d(TAG, "設定預覽視窗...");
  SurfaceHolder sh = this.sv.getHolder();
  sh.addCallback(this.cc);
  sh.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);

  Log.d(TAG, "設定拍照頁面...");
  this.hidePhotoBtn.setVisibility(View.GONE);

  // 按鈕外按自動對焦
  autoFocus.setOnClickListener(new Button.OnClickListener() {

   @Override
   public void onClick(View v) {
    cc.getCarema().autoFocus(new AutoFocusCallback() {
     @Override
     public void onAutoFocus(boolean success, Camera camera) {

     }
    });
   }
  });
  //前往照片列表
  picList.setOnClickListener(new Button.OnClickListener() {

   @Override
   public void onClick(View v) {
    goToPicList();
   }
  });
  
 }

 public void takePhoto(View v) {
  Log.d(TAG, "拍照...");
  // 需要三個 callback:快門、處理 raw data、處理 jpg
  // 拍照時自動對焦
  this.cc.getCarema().autoFocus(new AutoFocusCallback() {
   @Override
   public void onAutoFocus(boolean success, Camera camera) {
    if (success) {
     camera.takePicture(sc, rc, jc);
    }
   }
  });
 }

 public void hidePhoto(View v) {
  Log.d(TAG, "設定拍照頁面...");
  this.takePhotoBtn.setVisibility(View.VISIBLE);// 顯示拍照按鈕
  this.hidePhotoBtn.setVisibility(View.GONE); // 隱藏重拍按鈕

  Log.d(TAG, "回到拍照功能,需重新啟動預覽...");
  this.cc.getCarema().startPreview();
 }

 public void showPhoto(String picPath) {
  Log.d(TAG, "取得照片路徑:" + picPath);
  Log.d(TAG, "設定照片頁面...");
  this.takePhotoBtn.setVisibility(View.GONE);
  this.hidePhotoBtn.setVisibility(View.VISIBLE);

 }

 //前往照片列表
  public void goToPicList(){
   Intent intent=new Intent(this,PhotoList.class);
   startActivity(intent);
  }

}

CameraCallback.java
package tw.android;

import java.io.IOException;

import android.hardware.Camera;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceHolder.Callback;


public class CameraCallback implements Callback {

    private static final String TAG = "CameraCallback";
    private Camera carema;

    public Camera getCarema() {
        return this.carema;
    }

    public void surfaceCreated(SurfaceHolder holder) {
        Log.d(TAG, "啟動相機...");
        this.carema = Camera.open();
        try {
            Log.d(TAG, "設定預覽視窗");
            this.carema.setPreviewDisplay(holder);
        }
        catch (IOException e) {
            Log.e(TAG, e.getMessage(), e);
        }
    }

    public void surfaceChanged(SurfaceHolder holder, int format, int width,
            int height) {
        Log.d(TAG, "開始預覽...");
        this.carema.setDisplayOrientation(90); //相機旋轉90度
        this.carema.startPreview();
    }

    public void surfaceDestroyed(SurfaceHolder holder) {
        Log.d(TAG, "停止預覽...");
        this.carema.stopPreview();
        Log.d(TAG, "釋放相機資源...");
        this.carema.release();
        this.carema = null;
    }

 
}

JpgCallback.java
package tw.android;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;

import android.annotation.SuppressLint;
import android.content.SharedPreferences;
import android.hardware.Camera;
import android.hardware.Camera.PictureCallback;
import android.os.Environment;
import android.util.Log;

public class JpgCallback implements PictureCallback {

    private static final String TAG = "JpgCallback";
    private String picPath;
    private TakeAPhotoActivity act;
    int number;
    public JpgCallback(TakeAPhotoActivity act) {
        super();
        this.act = act;
    }

    @Override
    public void onPictureTaken(byte[] data, Camera camera) {
        Log.d(TAG, "處理 JPG 資料,輸出 jpg 檔...");
        /*-- 2015-09-11 相機旋轉90度後,照片需要跟著旋轉90度 --*/
        Bitmap srcBmp, dstBmp;
        srcBmp= BitmapFactory.decodeByteArray(data, 0, data.length);
        Matrix matrix=new Matrix();
        matrix.reset();
        matrix.postRotate(90f);
        dstBmp= Bitmap.createBitmap(srcBmp, 0, 0, srcBmp.getWidth(), srcBmp.getHeight(), matrix, true);
        /*-- 2015-09-11 --*/
        FileOutputStream os = null;
        try {
            File pic = this.createPicFile();
            os = new FileOutputStream(pic);
            dstBmp.compress(Bitmap.CompressFormat.JPEG, 100, os); //2015-09-11 Bitmap 轉回 byte[]
            os.write(data);
        }
        catch (IOException e) {
            Log.e(TAG, e.getMessage(), e);
        }
        finally {
            if (os != null) {
                try {
                    os.close();
                }
                catch (IOException e) {
                }
            }
        }
        Log.d(TAG, "輸出 JPG 完成");
        // 顯示照片
        this.act.showPhoto(this.picPath);
    }

    @SuppressLint("DefaultLocale")
 private File createPicFile() {
        File sdDir = Environment.getExternalStorageDirectory();
        Log.d(TAG, "sdDir" + sdDir);
        File picDir = new File(sdDir, "takePic"); //建立放置照片資料夾
        if (!picDir.exists()) {
            picDir.mkdir();
        }
        long ctm =System.currentTimeMillis(); //照片名
        
        /* SharedPreferences */
        try {
   SharedPreferences preferencesGet = this.act
     .getSharedPreferences("takePic",
       android.content.Context.MODE_PRIVATE);
   number=preferencesGet.getInt("number", 0); //照片數量
   
  } catch (Exception e) {

  }
        
  SharedPreferences preferencesSave = this.act
    .getSharedPreferences("takePic",
      android.content.Context.MODE_PRIVATE);
  SharedPreferences.Editor editor = preferencesSave.edit();
  
  Log.d(TAG,number+"");
  number++; //照片數量+1
  editor.putInt("number", number);
  editor.putLong(Integer.toString(number), ctm); //儲存照片名
  editor.commit();
  
  
        String fileName = String.format("%d.jpg", ctm);
        File pic = new File(picDir, fileName);
        this.picPath = pic.getAbsolutePath();
        Log.d(TAG, "照片路徑:" + this.picPath);
        return pic;
    }
}
RawCallback.java
package tw.android;

import android.hardware.Camera;
import android.hardware.Camera.PictureCallback;
import android.util.Log;

public class RawCallback implements PictureCallback {

    private static final String TAG = "RawCallback";

    @Override
    public void onPictureTaken(byte[] data, Camera camera) {
        Log.d(TAG, "處理 Raw data...");
    }

}

ShCallback.java
package tw.android;

import android.hardware.Camera.ShutterCallback;
import android.util.Log;

public class ShCallback implements ShutterCallback {

    private static final String TAG = "ShCallback";

    @Override
    public void onShutter() {
        Log.d(TAG, "啟動快門...");
    }
}

PhotoList.java 列出照片
package tw.android;

import java.io.File;

import android.app.Activity;
import android.content.SharedPreferences;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TableLayout;
import android.widget.TableRow;
import android.widget.TableRow.LayoutParams;

public class PhotoList extends Activity {

 private Button[] detelPic;
 private String[] dataName;

private int number;

 private int id;

 @Override
 public void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.photo_list);
  
  setTable();
 }


 // 排版
 public void setTable() {

  try {
   SharedPreferences preferencesGet = getApplicationContext()
     .getSharedPreferences("takePic",
       android.content.Context.MODE_PRIVATE);
   number=preferencesGet.getInt("number", 0);//取出照片數量
   dataName = new String[number];
   Log.i("number", number+"");
   for(int i = 0; i < number; i++){ 
    dataName[i]=String.valueOf(preferencesGet.getLong(Integer.toString(i+1), 0)); //放入照片名稱
    Log.i("dataName[i]", dataName[i]+"");
   }

  } catch (Exception e) {

  }
  
  
  TableLayout t1 = (TableLayout) findViewById(R.id.tableSet);
  t1.removeAllViews();
  TableRow.LayoutParams tP = new TableRow.LayoutParams(
    LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT, 1f);

  tP.setMargins(0, 0, 0, 20);

  detelPic = new Button[number];
  for (int i = 0; i < number; i++) { // 列
   TableRow row = new TableRow(this);
   ImageView iv = new ImageView(this);
   String picPath = "/storage/emulated/0/takePic/" + dataName[i]
     + ".jpg";
   Uri uri = Uri.fromFile(new File(picPath));
   iv.setLayoutParams(tP);
   iv.setImageURI(uri);
   row.addView(iv, 0);

   // 刪除button
   detelPic[i] = new Button(this);
   detelPic[i].setText("刪除");
   detelPic[i].setId(i);
   detelPic[i].setOnClickListener(dp); // 動作
   row.addView(detelPic[i], 1);

   t1.addView(row);
  }

 }

 private OnClickListener dp = new OnClickListener() {
  public void onClick(View v) {

   id = v.getId();
   // 刪除照片
   File file = new File("/storage/emulated/0/takePic/" + dataName[id]
     + ".jpg");
   file.delete();

   
   setTable();//重整
  }
 };

}

take_a_photo_activity.xml //拍照layout


    
  
    
 
    

    

    


photo_list.xml //照相列表 layout


    

        
        
    


檔案下載:
https://github.com/terryyamg/AndroidCamera
參考來源:
1.http://cw1057.blogspot.tw/2011/12/android-camera_09.html
2.http://stackoverflow.com/questions/8058122/where-to-put-autofocus-in-the-class-android-camera
3.http://stackoverflow.com/questions/5486529/delete-file-from-internal-storage
4.http://stackoverflow.com/questions/10660598/android-camera-preview-orientation-in-portrait-mode 
(2015-09-11 update)
5. http://rincliu.com/blog/2013/11/18/camera/
6.http://bingtian.iteye.com/blog/642128