问题背景:
大家好,我在安卓机拍照的过程中发现,使用原生相机拍照时,屏幕显示的画面范围比最后生成的照片要小。
下面给出具体的情况,请大家帮忙分析:
拍照时屏幕显示的画面:
实际照片内容:
可以看到,屏幕上呈现的画面只是照片的一部分,如示意图所示:
原生的拍照程序会有以上问题,需要通过camera API直接控制摄像头。
上面的问题只需要将surfaceView旋转90度就能解决,在代码中为: camera.setDisplayOrientation(90);
下面是源码:(参考《Android4高级编程》)
package com.example.haveimgfun;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.hardware.Camera;
import android.hardware.Camera.AutoFocusCallback;
import android.hardware.Camera.PictureCallback;
import android.hardware.Camera.ShutterCallback;
@SuppressLint("NewApi")
public class CameraActivity extends Activity implements SurfaceHolder.Callback{
private Camera camera;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_camera);
SurfaceView surface = (SurfaceView)findViewById(R.id.surfaceView);
SurfaceHolder holder = surface.getHolder();
holder.addCallback(this);
holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
holder.setFixedSize(400, 300);
//Button to take picture
Button snap = (Button)findViewById(R.id.buttonTakePicture);
snap.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
takePicture();
}
});
//Button to auto focus
Button autofocus = (Button)findViewById(R.id.buttonAutofocus);
autofocus.setOnClickListener(new OnClickListener(){
public void onClick(View v){
doAutoFocus();
}
});
}
@Override
public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {
// TODO Auto-generated method stub
camera.cancelAutoFocus(); //release auto fucus 2如果要实现连续的自动对焦,这一句必须加上
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
// TODO Auto-generated method stub
try {
camera.setPreviewDisplay(holder);
camera.startPreview();
camera.setDisplayOrientation(90); //by me rotate 90
//camera.startFaceDetection();
// TODO Draw over the preview if required.
} catch (IOException e) {
Log.d("TAG", e.getMessage());
}
}
@Override
public void surfaceDestroyed(SurfaceHolder arg0) {
// TODO Auto-generated method stub
camera.setPreviewCallback(null) ; //debug
camera.stopPreview();
camera.release();
camera=null;
}
@Override
protected void onPause() {
super.onPause();
//camera.release();
}
@Override
protected void onResume() {
super.onResume();
camera = Camera.open();
//get focus area number
}
//define shutterCallback
ShutterCallback shutterCallback = new ShutterCallback() {
public void onShutter() {
// TODO Do something when the shutter closes.
}
};
PictureCallback rawCallback = new PictureCallback() {
public void onPictureTaken(byte[] data, Camera camera) {
// TODO Do something with the image RAW data.
}
};
//stroe the picture in format jpeg
PictureCallback jpegCallback = new PictureCallback() {
public void onPictureTaken(byte[] data, Camera camera) {
// Save the image JPEG data to the SD card
FileOutputStream outStream = null;
try {
String path = Environment.getExternalStorageDirectory() +
"/test.jpg";
outStream = new FileOutputStream(path);
outStream.write(data);
outStream.close();
finish(); //finish current activity
} catch (FileNotFoundException e) {
Log.e("TAG", "File Note Found", e);
} catch (IOException e) {
Log.e("TAG", "IO Exception", e);
}
}
};
//handle button snap
private void takePicture() {
camera.takePicture(shutterCallback, rawCallback, jpegCallback);
}
//handle button auto focus
private void doAutoFocus(){
Camera.Parameters parameters = camera.getParameters();
if(parameters.getSupportedFocusModes().contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)){
parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
camera.autoFocus(new AutoFocusCallback(){
public void onAutoFocus(boolean success, Camera camera){
Log.i("TAG","AutoFocus:"+(success?"Succeeded":"Failed"));
}
});
}
}
}
</pre><pre>xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<LinearLayout
android:layout_alignParentTop="true"
android:id="@+id/linearLayout1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<Button
android:id="@+id/buttonAutofocus"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Autofocus" />
<Button
android:id="@+id/buttonFaces"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Faces" />
<Button
android:id="@+id/buttonFocusDistances"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Distances" />
<Button
android:id="@+id/buttonTakePicture"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Snap" />
<Button
android:id="@+id/buttonExif"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Exif" />
</LinearLayout>
<SurfaceView
android:layout_below="@id/linearLayout1"
android:id="@+id/surfaceView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</RelativeLayout>之前遇到一个bug:
当我使用下面代码时:
public void surfaceDestroyed(SurfaceHolder holder) {
//camera.stopFaceDetection();
camera.stopPreview();
}
@Override
protected void onPause() {
super.onPause();
camera.release();
}
会报Method called after release()的bug
将代码改为下面所示则没有bug。可能是因为camera.release()的时间问题,若放在onPause()中,销毁之后还会用到camera。有时间可以仔细分析。
@Override
public void surfaceDestroyed(SurfaceHolder arg0) {
// TODO Auto-generated method stub
camera.setPreviewCallback( null) ; //debug
camera.stopPreview();
camera.release();
camera= null;
}
@Override
protected void onPause() {
super.onPause();
//camera.release();
}
在Android开发中,原生相机应用在拍照时出现屏幕显示画面范围与实际照片不一致的问题。通过分析,发现需要直接使用camera API来控制摄像头。通过设置camera.setDisplayOrientation(90)可以解决屏幕预览旋转问题。此外,调整相机释放的时机能避免相关bug,例如将camera.release()移出onPause()方法。

被折叠的 条评论
为什么被折叠?



