我正在開發一個Android應用程序,使用Android相機API打開預覽並從中拍攝照片。該應用程序只能在肖像模式下工作,並且必須可以同時使用設備的前置攝像頭和後置攝像頭(如果設備具有兩個攝像頭)。使用Android相機拍攝的照片的奇怪尺寸
我已經在我的應用程序中打開預覽,我已經正確設置了顯示方向(使用方法旋轉90度的方向:mCamera.setDisplayOrientation(90)),以便可以在縱向模式下查看應用程序預覽,並且我添加了按鈕,可以在前後攝像頭之間切換。所有這些東西在應用程序中正常工作。
問題是當我拍照時:爲了以正確的方式(以肖像)旋轉拍攝的照片,我將設備的方向設爲對角,並將圖片旋轉爲所需的方向。但是,當照片保存到圖庫中時,照片尺寸很奇怪:如果使用前置相機拍攝,則照片尺寸爲全屏,而不是使用後置照相機拍攝。我的目標是始終全屏照相。
這兩個屏幕截圖顯示的問題:
---後相機的照片:
---前置攝像頭PHOTO:
這裏,有我的CameraPreview代碼:
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
if (mHolder.getSurface() == null){
return;
}
try {
mCamera.stopPreview();
} catch (Exception e){
}
try {
// Start preview in portrait mode
mCamera.setDisplayOrientation(90);
// Set the list of supported preview size in the related variable
if(mCamera != null){
if(mCamera.getParameters().getSupportedPreviewSizes() != null){
mSupportedPreviewSizes = mCamera.getParameters().getSupportedPreviewSizes();
}
}
// Get the parameters of camera
Camera.Parameters parameters = mCamera.getParameters();
// Set output format to NV21 (which is guranteed to be supported on all devices)
parameters.setPreviewFormat(ImageFormat.NV21);
// Set the correct preview size (after applying the getOptimalPreviewSize)
if(mPreviewSize != null) {
parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
Log.d(TAG,"Preview size is ("+mPreviewSize.width+";"+mPreviewSize.height+")");
// initializing bitmap and pixels
bitmap = Bitmap.createBitmap(mPreviewSize.width, mPreviewSize.height, Bitmap.Config.ARGB_8888);
pixels = new int[mPreviewSize.width * mPreviewSize.height];
}
// Correct the size - orientation of picture taken
if(isTablet(getContext()) == Boolean.FALSE){
onOrientationChanged(getScreenRotationOnPhone(),parameters);
}else{
onOrientationChanged(getScreenRotationOnTablet(),parameters);
}
mCamera.setPreviewDisplay(mHolder);
// Set to turn the Flash ON
// parameters.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
mCamera.setParameters(parameters);
mCamera.setPreviewDisplay(mHolder);
mCamera.startPreview();
// Call the setPreviewCallback and onPreviewFrame to get the incoming frame
mCamera.setPreviewCallback(new Camera.PreviewCallback() {
@Override
public void onPreviewFrame (byte[] data, Camera camera){
Log.i(TAG, "Ma entro nella onPreviewFrame?");
Camera.Parameters parameters = mCamera.getParameters();
int format = parameters.getPreviewFormat();
Log.i(TAG, "Il formato del frame e': " + format);
//YUV formats require more conversion
if (format == ImageFormat.NV21 || format == ImageFormat.YUY2 || format == ImageFormat.NV16) {
int w = parameters.getPreviewSize().width;
int h = parameters.getPreviewSize().height;
}
}
});
} catch (Exception e){
Log.d(TAG, "Error starting camera preview: " + e.getMessage());
}
}
private int getScreenRotationOnPhone() {
final Display display = ((WindowManager)getContext().getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
if(display.getRotation() == Surface.ROTATION_0){
System.out.println("SCREEN_ORIENTATION_PORTRAIT");
return Surface.ROTATION_0;
}else if(display.getRotation() == Surface.ROTATION_90){
System.out.println("SCREEN_ORIENTATION_LANDSCAPE");
return Surface.ROTATION_90;
}else if(display.getRotation() == Surface.ROTATION_180){
System.out.println("SCREEN_ORIENTATION_REVERSE_PORTRAIT");
return Surface.ROTATION_180;
}else if(display.getRotation() == Surface.ROTATION_270){
System.out.println("SCREEN_ORIENTATION_REVERSE_LANDSCAPE");
return Surface.ROTATION_270;
}else{
System.out.println("SCREEN_ORIENTATION_NOT_ADMISSIBLE");
return -1;
}
}
private int getScreenRotationOnTablet() {
final Display display = ((WindowManager)getContext().getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
if(display.getRotation() == Surface.ROTATION_0){
System.out.println("SCREEN_ORIENTATION_LANDSCAPE");
return Surface.ROTATION_0;
}else if(display.getRotation() == Surface.ROTATION_90){
System.out.println("SCREEN_ORIENTATION_REVERSE_PORTRAIT");
return Surface.ROTATION_90;
}else if(display.getRotation() == Surface.ROTATION_180){
System.out.println("SCREEN_ORIENTATION_REVERSE_LANDSCAPE");
return Surface.ROTATION_180;
}else if(display.getRotation() == Surface.ROTATION_270){
System.out.println("SCREEN_ORIENTATION_PORTRAIT");
return Surface.ROTATION_270;
}else{
System.out.println("SCREEN_ORIENTATION_NOT_ADMISSIBLE");
return -1;
}
}
public boolean isTablet(Context context) {
boolean xlarge = ((context.getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) == 4);
boolean large = ((context.getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) == Configuration.SCREENLAYOUT_SIZE_LARGE);
return (xlarge || large);
}
public void onOrientationChanged(int orientation, Camera.Parameters mParameters) {
android.hardware.Camera.CameraInfo info = new android.hardware.Camera.CameraInfo();
android.hardware.Camera.getCameraInfo(CameraActivity.getOpenedCamera(), info);
Log.i(TAG, "onOrientationChanged -> Camera opened actually is: "+CameraActivity.getOpenedCamera());
orientation = (orientation + 45)/90 * 90;
int rotation = 0;
if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
rotation = (info.orientation - orientation + 360) % 360;
} else { // back-facing camera
rotation = (info.orientation + orientation) % 360;
}
Log.i(TAG, "onOrientationChanged -> Orientation of pictures setted to: "+rotation);
mParameters.setRotation(rotation);
}
在這裏,有CameraActivity的onPictureTaken代碼,切換攝像頭的方法:使用工具的這種方法
@Override
public void onPictureTaken(byte[] data, Camera camera) {
// TODO Auto-generated method stub
File pictureFile = Utility.getOutputMediaFile();
if (pictureFile == null){
Toast.makeText(this, "Couldn't create file", Toast.LENGTH_SHORT).show();
Log.d(TAG,"Couldn't create file");
return;//?
}else{
try{
FileOutputStream fos = new FileOutputStream(pictureFile);
fos.write(data);
fos.flush();
fos.close();
}
catch (FileNotFoundException e){
Toast.makeText(this, "File not found exception", Toast.LENGTH_SHORT).show();
Log.d(TAG,"File not found: "+e.getMessage());
}
catch (IOException e){
Toast.makeText(this, "IO Exception", Toast.LENGTH_SHORT).show();
Log.d(TAG, "Error accessing file: "+e.getMessage());
}
//Per farle comparire subito nella cartella le foto:
this.mPictureFile = pictureFile;
MediaScannerConnection.scanFile(getApplicationContext(),
new String[]{this.mPictureFile.toString()}, null,
new MediaScannerConnection.OnScanCompletedListener() {
public void onScanCompleted(String path, Uri uri) {
Log.i(TAG, "ExternalStorage Scanned " + path + ":");
Log.i(TAG, "ExternalStorage -> uri=" + uri);
}
});
camera.startPreview();
imageSaved.sendEmptyMessage(0);
}
}
public void switchCam(){
if (hasFrontCam == Boolean.TRUE && hasBackCam == Boolean.TRUE) {
// The phone has front camera and back camera
if(openedCam==Camera.CameraInfo.CAMERA_FACING_BACK){
//Chiudi la preview
if (mCamera!=null){
mCamera.setPreviewCallback(null);
mCamera.stopPreview();
mCamera.release();
mCamera = null;
}
//Apri la nuova camera
mCamera = Camera.open(Camera.CameraInfo.CAMERA_FACING_FRONT);
init();
openedCam=Camera.CameraInfo.CAMERA_FACING_FRONT;
}else{
//openedCam==Camera.CameraInfo.CAMERA_FACING_FRONT
//Chiudi la preview
if (mCamera!=null){
mCamera.setPreviewCallback(null);
mCamera.stopPreview();
mCamera.release();
mCamera = null;
}
//Apri la nuova camera
mCamera = Camera.open(Camera.CameraInfo.CAMERA_FACING_BACK);
//riprendi la preview
init();
openedCam=Camera.CameraInfo.CAMERA_FACING_BACK;
}
}
}
:
/** Create a File for saving an image */
public static File getOutputMediaFile(){
String state = Environment.getExternalStorageState();
if(state.equals(Environment.MEDIA_MOUNTED)){
File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), "MyApp");
if (!mediaStorageDir.exists()){
if (!mediaStorageDir.mkdirs()){
Log.d(TAG,"Failed to create directory");
return null;
}
}
// Create a media file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
File mediaFile;
mediaFile = new File(mediaStorageDir.getPath() + File.separator + "IMG_" + timeStamp + ".jpg");
return mediaFile;
}else if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
Log.d(TAG,"External storage not writable but only readable");
return null;
}else{
Log.d(TAG,"External storage not writable");
return null;
}
}
有人可以幫助我解決這個問題?
我注意到圖片翻轉了。是對的嗎? – hasan83 2014-12-03 10:04:29
在前後凸輪之間切換的代碼在哪裏。 – hasan83 2014-12-03 10:08:49
是的,圖片被翻轉以糾正其保存到Gallery中的方向。改變的作品,實際上照片的方向是正確的。我還添加了切換攝像頭的方法。 – user140888 2014-12-03 10:24:48