--------------------------------------------
1. Camera
--------------------------------------------
Android中應用相機功能,一般有兩種:
- Method 1:調用系統相機,使用Intent跳轉到系統相機,action
- 在 manifests xml 中 加入 Camera 權限 和 外部存取權限 來抓取相機拍照後所回傳的結果相片。
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
- 在 Main.java 中所使用的 function 方法:
private final static int CAMERA = 66 ;
// get Display Height and Widht pixel
private DisplayMetrics metrics;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 抓取 display 變數
metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
}
private void goCamera() {
// Start an intent for Camera Capture with ResultActivity
Intent cameraIntent = new Intent(
android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
try {
cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, getImageUri());
if (cameraIntent.resolveActivity(getPackageManager()) != null) {
startActivityForResult(cameraIntent, CAMERA); //設定回傳 resultCode
}
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
// Put and Draw Selected Photo in SurfaceView
Uri imageUri = null;
InputStream inputStream = null;
if ( requestCode == CAMERA ){
// 將拍照完的圖片儲存再 m_imagePath 路徑內,以便讀圖編輯
try {
if (data!=null){
// 其他相機程式回傳的 uri
imageUri = data.getData();
} else {
// 內建相機程式回傳的 uri
File file = new File(m_imagePath);
imageUri = Uri.fromFile(file);
}
inputStream = getContentResolver().openInputStream(imageUri);
try {
Bitmap getbp = ScaleLoadBitmapByOption(getBytesFromInputStream(inputStream),
metrics.widthPixels,
metrics.heightPixels);
}catch (OutOfMemoryError e) {
// Toast.makeText(Phone2.this, "Out Of Memory", Toast.LENGTH_SHORT).show();
} catch (IOException e) {
e.printStackTrace();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}
- Method 2. 自己寫的相機
1. SurfaceView顯示照相機中的預覽效果, - Camera類提供:
a. 一個 setPreviewDisplay( SurfaceHolder ) 的方法來連接 surfaceHolder, 並通過他來控制 surfaceView。
b. startPreview() 和 stopPreview() 來開启和關閉預覽.
b. startPreview() 和 stopPreview() 來開启和關閉預覽.
2. 開启相機.Camera.open() 這是個靜態方法,如果相機沒有別人用着,則會返回一個 相機引用,如果被人用着,則會拋出異常。
3. 不能放在構造方法或者 onCreate() 方法中,會照成沒有預覽效果.
4. 當開始拍照時,會依次調用:
a. shutter的onShutter()方法, shutter--拍照瞬間調用
b. raw的onPictureTaken方法 , raw--獲得沒有壓縮過的圖片數據
c. jpeg的onPictureTaken方法 . jpeg---返回jpeg的圖片數據
5. 透過控制裝置相機,來拍好圖片。
a. 其設置相關的参數:
Camera.Parameters parames = myCamera.getParameters(); //獲得参數對象
parames.setPictureFormat(PixelFormat.JPEG); //設置圖片格式
parames.setPreviewSize(640,480); //這裏面的参數只能是幾個特定的参數,否則會報錯. //(176*144,320*240,352*288,480*360,640*480)
myCamera.setParameters(parames);
b. 自動對焦方法:
myCamera.autoFocus(); //這個方法必須在startPreview()和stopPreview()中間。(有些手機沒有此功能)
AutoFocusCallback是自動對焦的接口,實現它必須實現public void onAutoFocus(boolean success, Camera camera)這個方法
- 在 manifests xml 中 加入 Camera 權限 和 外部存取權限 來抓取相機拍照後所回傳的結果相片。
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-feature android:name="android.hardware.camera.autofocus" />
- CameraTest_4.java -
import android.app.Activity;
....
import android.view.View.OnClickListener;
public class CameraTest_3 extends Activity implements Callback, OnClickListener, AutoFocusCallback {
SurfaceView mySurfaceView; //surfaceView聲明
SurfaceHolder holder; //surfaceHolder聲明
Camera myCamera; //相機聲明
String filePath="/sdcard/wjh.jpg"; //照片保存路徑
boolean isClicked = false; //是否點擊標識
//創建jpeg圖片回調數據對象
PictureCallback jpeg = new PictureCallback() {
@Override
public void onPictureTaken(byte[] data, Camera camera) {
// TODO Auto-generated method stub
try {// 獲得圖片
Bitmap bm = BitmapFactory.decodeByteArray(data, 0, data.length);
File file = new File(filePath);
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file));
bm.compress(Bitmap.CompressFormat.JPEG, 100, bos);//將圖片壓縮到流中
bos.flush();//輸出
bos.close();//關閉
}catch(Exception e) {
e.printStackTrace();
}
}
};
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE); //無標題
this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); //設置拍攝方向
setContentView(R.layout.main);
mySurfaceView = (SurfaceView)findViewById(R.id.surfaceView1); //獲得控件
holder = mySurfaceView.getHolder(); //獲得句柄
holder.addCallback(this); //添加回調
holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); //設置類型
mySurface.setOnClickListener(this); //設置監聽
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
// TODO Auto-generated method stub
//設置参數並開始預覽
Camera.Parameters params = myCamera.getParameters();
params.setPictureFormat(PixelFormat.JPEG);
params.setPreviewSize(640,480);
myCamera.setParameters(params);
myCamera.startPreview();
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
// TODO Auto-generated method stub
//開启相機
if(myCamera == null) {
myCamera = Camera.open();
try {
myCamera.setPreviewDisplay(holder);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
// TODO Auto-generated method stub
//關閉預覽並釋放資源
myCamera.stopPreview();
myCamera.release();
myCamera = null;
}
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
if(!isClicked) {
myCamera.autoFocus(this);//自動對焦
isClicked = true;
}else {
myCamera.startPreview();//開启預覽
isClicked = false;
}
}
@Override
public void onAutoFocus(boolean success, Camera camera) {
// TODO Auto-generated method stub
if(success) {
//設置参數,並拍照
Camera.Parameters params = myCamera.getParameters();
params.setPictureFormat(PixelFormat.JPEG);
params.setPreviewSize(640,480);
myCamera.setParameters(params);
myCamera.takePicture(null, null, jpeg);
}
}
}
參考資料:
- android --相機使用詳解概述:http://fecbob.pixnet.net/blog/post/39322397-android---%E7%9B%B8%E6%A9%9F%E4%BD%BF%E7%94%A8%E8%A9%B3%E8%A7%A3%E6%A6%82%E8%BF%B0
- 【Android】開啟相機-照相功能與相簿-相片集並讀取相片匯入至程式:http://dean-android.blogspot.tw/2013/05/android.html
--------------------------------------------
2. Gallery
--------------------------------------------
讀取 Android gallery 中 相簿相片:
- 在 manifests xml 中 加入 外部存取權限 來抓取相簿後所回傳的結果相片。
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
- 在 Main.java 中所使用的 function 方法:
private final static int PHOTO= 66 ;
// get Display Height and Widht pixel
private DisplayMetrics metrics;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 抓取 display 變數
metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
}
private void goAlbums() {
// Start an intent for user Albums with ResultActivity
Intent intent = new Intent();
intent.setType("image/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(intent, PHOTO);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
Uri imageUri = null;
InputStream inputStream = null;
if (requestCode == PHOTO && data != null)
{
try{
imageUri = data.getData();
inputStream = getContentResolver().openInputStream(imageUri);
try {
Bitmap getbp = ScaleLoadBitmapByOption(getBytesFromInputStream(inputStream), // bytes[]
metrics.widthPixels,
metrics.heightPixels));
}catch (OutOfMemoryError e) {
// Toast.makeText(Phone2.this, "Out Of Memory", Toast.LENGTH_SHORT).show();
}
} catch (IOException e) {
// Toast.makeText(Phone2.this, "File Error", Toast.LENGTH_SHORT).show();
e.printStackTrace();
}
}
}
--------------------------------------------
3. Sub-Function
--------------------------------------------
//--------------------------------------------
// LoadFileToBitmap and TransFileToBytes
//--------------------------------------------
private Bitmap ScaleLoadBitmapByOption(byte[] data, int dspW, int dspH){
// //Only decode image size. Not whole image
// BitmapFactory.Options options = new BitmapFactory.Options();
// options.inJustDecodeBounds = true;
// BitmapFactory.decodeByteArray(data, 0, data.length, options);
// //The new size to decode to dspW and dspH
// //Now we have image width and height. We should find the correct scale value. (power of 2)
// int width=options.outWidth; //
// int height=options.outHeight;
// float scale = 0;
// if (width > dspW || height > dspH){
// if (height > width){
// scale = height/dspH;
// }else if (width > height){
// scale = width/dspW;
// }
// }else{
// scale = 1;
// }
//Decode again with inSampleSize
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPurgeable = true;
options.inInputShareable = true;
// options.inSampleSize=(int)scale;
return BitmapFactory.decodeByteArray(data, 0, data.length, options);
}
private static byte[] getBytesFromInputStream(InputStream is) throws IOException {
ByteArrayOutputStream outstream = new ByteArrayOutputStream();
byte[] buffer = new byte[1024]; //
int len = -1;
while ((len = is.read(buffer)) != -1) {
outstream.write(buffer, 0, len);
}
outstream.close();
return outstream.toByteArray();
}
參考資料:
- android:图片处理(本地uri图片显示,本地uri转为bitmap和网络uri转为bitmap显示) :http://2711082222.blog.163.com/blog/static/106302249201236101341323/
- Android 通过Uri获取Bitmap对象 :http://blog.sina.com.cn/s/blog_5de73d0b0100zfm8.html
沒有留言:
張貼留言