我试图控制Android相机拍照在肖像的应用程序,但是当我保存的图片,它的景观。 我旋转的图像90分的成绩与setCameraDisplayOrientation()
方法,但不起作用。
然后我发现这个职位 ,但TAG_ORIENTATION
为0
(未定义)。 如果我抓住这个数值并应用旋转值,也不管用。
我怎么可以在人像照片,并具有良好的方向保存呢?
/** Initializes the back/front camera */
private boolean initPhotoCamera() {
try {
camera = getCameraInstance(selected_camera);
Camera.Parameters parameters = camera.getParameters();
// parameters.setPreviewSize(width_video, height_video);
// parameters.set("orientation", "portrait");
// parameters.set("rotation", 1);
// camera.setParameters(parameters);
checkCameraFlash(parameters);
// camera.setDisplayOrientation( 0);
setCameraDisplayOrientation(selected_camera, camera);
surface_view.getHolder().setFixedSize(width_video, height_video);
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(width_video, height_video);
surface_view.setLayoutParams(lp);
camera.lock();
surface_holder = surface_view.getHolder();
surface_holder.addCallback(this);
surface_holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
setPreviewCamera();
} catch (Exception e) {
Log.v("RecordVideo", "Could not initialize the Camera");
return false;
}
return true;
}
public void setCameraDisplayOrientation(int cameraId, Camera camera) {
Camera.CameraInfo info = new Camera.CameraInfo();
Camera.getCameraInfo(cameraId, info);
int rotation = getWindowManager().getDefaultDisplay().getRotation();
int degrees = 0;
switch (rotation) {
case Surface.ROTATION_0: degrees = 0; break;
case Surface.ROTATION_90: degrees = 90; break;
case Surface.ROTATION_180: degrees = 180; break;
case Surface.ROTATION_270: degrees = 270; break;
}
int result;
if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
result = (info.orientation + degrees) % 360;
result = (360 - result) % 360; // compensate the mirror
} else { // back-facing
result = (info.orientation - degrees + 360) % 360;
}
camera.setDisplayOrientation(result);
}
public static Bitmap rotate(Bitmap bitmap, int degree) {
int w = bitmap.getWidth();
int h = bitmap.getHeight();
Matrix mtx = new Matrix();
// mtx.postRotate(degree);
mtx.setRotate(degree);
return Bitmap.createBitmap(bitmap, 0, 0, w, h, mtx, true);
}
@Override
public void onPictureTaken(byte[] data, Camera camera) {
String timeStamp = Calendar.getInstance().getTime().toString();
output_file_name = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM) + File.separator + timeStamp + ".jpeg";
File pictureFile = new File(output_file_name);
if (pictureFile.exists()) {
pictureFile.delete();
}
try {
FileOutputStream fos = new FileOutputStream(pictureFile);
fos.write(data);
Bitmap realImage = BitmapFactory.decodeFile(output_file_name);
ExifInterface exif=new ExifInterface(pictureFile.toString());
Log.d("EXIF value", exif.getAttribute(ExifInterface.TAG_ORIENTATION));
if(exif.getAttribute(ExifInterface.TAG_ORIENTATION).equalsIgnoreCase("6")){
realImage= rotate(realImage, 90);
} else if(exif.getAttribute(ExifInterface.TAG_ORIENTATION).equalsIgnoreCase("8")){
realImage= rotate(realImage, 270);
} else if(exif.getAttribute(ExifInterface.TAG_ORIENTATION).equalsIgnoreCase("3")){
realImage= rotate(realImage, 180);
} else if(exif.getAttribute(ExifInterface.TAG_ORIENTATION).equalsIgnoreCase("0")){
realImage= rotate(realImage, 45);
}
boolean bo = realImage.compress(Bitmap.CompressFormat.JPEG, 100, fos);
fos.close();
Log.d("Info", bo + "");
} catch (FileNotFoundException e) {
Log.d("Info", "File not found: " + e.getMessage());
} catch (IOException e) {
Log.d("TAG", "Error accessing file: " + e.getMessage());
}
}
Answer 1:
问题是,当我保存的图像我没有做好。
@Override
public void onPictureTaken(byte[] data, Camera camera) {
String timeStamp = new SimpleDateFormat( "yyyyMMdd_HHmmss").format( new Date( ));
output_file_name = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM) + File.separator + timeStamp + ".jpeg";
File pictureFile = new File(output_file_name);
if (pictureFile.exists()) {
pictureFile.delete();
}
try {
FileOutputStream fos = new FileOutputStream(pictureFile);
Bitmap realImage = BitmapFactory.decodeByteArray(data, 0, data.length);
ExifInterface exif=new ExifInterface(pictureFile.toString());
Log.d("EXIF value", exif.getAttribute(ExifInterface.TAG_ORIENTATION));
if(exif.getAttribute(ExifInterface.TAG_ORIENTATION).equalsIgnoreCase("6")){
realImage= rotate(realImage, 90);
} else if(exif.getAttribute(ExifInterface.TAG_ORIENTATION).equalsIgnoreCase("8")){
realImage= rotate(realImage, 270);
} else if(exif.getAttribute(ExifInterface.TAG_ORIENTATION).equalsIgnoreCase("3")){
realImage= rotate(realImage, 180);
} else if(exif.getAttribute(ExifInterface.TAG_ORIENTATION).equalsIgnoreCase("0")){
realImage= rotate(realImage, 90);
}
boolean bo = realImage.compress(Bitmap.CompressFormat.JPEG, 100, fos);
fos.close();
((ImageView) findViewById(R.id.imageview)).setImageBitmap(realImage);
Log.d("Info", bo + "");
} catch (FileNotFoundException e) {
Log.d("Info", "File not found: " + e.getMessage());
} catch (IOException e) {
Log.d("TAG", "Error accessing file: " + e.getMessage());
}
}
public static Bitmap rotate(Bitmap bitmap, int degree) {
int w = bitmap.getWidth();
int h = bitmap.getHeight();
Matrix mtx = new Matrix();
// mtx.postRotate(degree);
mtx.setRotate(degree);
return Bitmap.createBitmap(bitmap, 0, 0, w, h, mtx, true);
}
Answer 2:
该setCameraDisplayOrientation()方法可以让你改变预览的方式,而不影响图像是如何记录(显示源 )。
为了改变实际记录的图像,你需要设置相机的旋转参数。 你不喜欢这样:
//STEP #1: Get rotation degrees
Camera.CameraInfo info = new Camera.CameraInfo();
Camera.getCameraInfo(Camera.CameraInfo.CAMERA_FACING_BACK, info);
int rotation = mActivity.getWindowManager().getDefaultDisplay().getRotation();
int degrees = 0;
switch (rotation) {
case Surface.ROTATION_0: degrees = 0; break; //Natural orientation
case Surface.ROTATION_90: degrees = 90; break; //Landscape left
case Surface.ROTATION_180: degrees = 180; break;//Upside down
case Surface.ROTATION_270: degrees = 270; break;//Landscape right
}
int rotate = (info.orientation - degrees + 360) % 360;
//STEP #2: Set the 'rotation' parameter
Camera.Parameters params = mCamera.getParameters();
params.setRotation(rotate);
mCamera.setParameters(params);
您的解决方案是一种因为你修改图像后,已经记录的一种解决方法。 该解决方案是更清洁,不要求所有这些“如果”保存图像前发言。
Answer 3:
您可以使用下面的方法来使用前置摄像头时,你的正确生成预览。
这个代码进入你的相机预览的surfaceChanged方法
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
int angleToRotate=CommonMethods.getRoatationAngle(mActivity, Camera.CameraInfo.CAMERA_FACING_FRONT);
mCamera.setDisplayOrientation(angleToRotate);
}
此代码可以被放入一个静态类
/**
* Get Rotation Angle
*
* @param mContext
* @param cameraId
* probably front cam
* @return angel to rotate
*/
public static int getRoatationAngle(Activity mContext, int cameraId) {
android.hardware.Camera.CameraInfo info = new android.hardware.Camera.CameraInfo();
android.hardware.Camera.getCameraInfo(cameraId, info);
int rotation = mContext.getWindowManager().getDefaultDisplay().getRotation();
int degrees = 0;
switch (rotation) {
case Surface.ROTATION_0:
degrees = 0;
break;
case Surface.ROTATION_90:
degrees = 90;
break;
case Surface.ROTATION_180:
degrees = 180;
break;
case Surface.ROTATION_270:
degrees = 270;
break;
}
int result;
if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
result = (info.orientation + degrees) % 360;
result = (360 - result) % 360; // compensate the mirror
} else { // back-facing
result = (info.orientation - degrees + 360) % 360;
}
return result;
}
您可以旋转图像这个way.This仅用于当拍摄图像时,我们要保存的图像
public static Bitmap rotate(Bitmap bitmap, int degree) {
int w = bitmap.getWidth();
int h = bitmap.getHeight();
Matrix mtx = new Matrix();
mtx.postRotate(degree);
return Bitmap.createBitmap(bitmap, 0, 0, w, h, mtx, true);
}
将被用于拍摄照片的方法
@Override
public void onPictureTaken(byte[] data, Camera camera) {
int angleToRotate = getRoatationAngle(MainActivity.this, Camera.CameraInfo.CAMERA_FACING_FRONT);
// Solve image inverting problem
angleToRotate = angleToRotate + 180;
Bitmap orignalImage = BitmapFactory.decodeByteArray(data, 0, data.length);
Bitmap bitmapImage = rotate(orignalImage, angleToRotate);
}
该bitmapImage
包含正确的图像。
Answer 4:
这个应该工作,ExifInterface并不适用于所有的工作制成品所以使用CameraInfo代替,只是让摄像机捕获图像与它的默认旋转,然后旋转上PictureCallback结果数据
private PictureCallback mPicture = new PictureCallback() {
@Override
public void onPictureTaken(byte[] data, Camera camera) {
File dir = new File(Constant.SDCARD_CACHE_PREFIX);
if (!dir.exists()) {
dir.mkdirs();
}
File pictureFile = new File(Constant.SDCARD_TAKE_PHOTO_CACHE_PREFIX);
try {
Bitmap realImage = BitmapFactory.decodeByteArray(data, 0, data.length);
android.hardware.Camera.CameraInfo info = new android.hardware.Camera.CameraInfo();
android.hardware.Camera.getCameraInfo(mCurrentCameraId, info);
Bitmap bitmap = rotate(realImage, info.orientation);
FileOutputStream fos = new FileOutputStream(pictureFile);
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos);
fos.close();
} catch (FileNotFoundException e) {
Log.d(TAG, "File not found: " + e.getMessage());
} catch (IOException e) {
Log.d(TAG, "Error accessing file: " + e.getMessage());
}
resultFileUri = Uri.fromFile(pictureFile);
startEffectFragment();
}
};
public static Bitmap rotate(Bitmap bitmap, int degree) {
int w = bitmap.getWidth();
int h = bitmap.getHeight();
Matrix mtx = new Matrix();
mtx.postRotate(degree);
return Bitmap.createBitmap(bitmap, 0, 0, w, h, mtx, true);
}
Answer 5:
我没有代表发表评论,所以我不得不离开另一个答案相反,虽然Nvhausid答案是真棒,值得信贷。 简单,优雅,它适用于三星设备,其中的Exif和媒体光标不会在正面和背面摄像头。
答案是缺少对我来说唯一的办法就是从相机面向用户处理镜像。
下面是该代码的变化:
Bitmap bitmap = rotate(realImage, info.orientation, info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT);
而新的旋转方法:
public static Bitmap rotate(Bitmap bitmap, int degree, boolean mirror) {
int w = bitmap.getWidth();
int h = bitmap.getHeight();
Matrix mtx = new Matrix();
if(mirror)mtx.setScale(1,-1);
mtx.postRotate(degree);
return Bitmap.createBitmap(bitmap, 0, 0, w, h, mtx, true);
}
Answer 6:
我找到你了有力的回答,我只是满足了同样的问题,解决它,但不保存文件。该解决方案是注册一个OrientationEventListener获得定向每当它改变。 http://www.androidzeitgeist.com/2013/01/fixing-rotation-camera-picture.html这里给details.My代码如下:
private CameraOrientationListener myOrientationListener;
private int rotation;
protected void onCreate(Bundle savedInstanceState) {
setListeners();
rotation = setCameraDisplayOrientation(CameraActivity.this, Camera.getNumberOfCameras()-1, mCamera);
}
public void setListeners(){
myOrientationListener = new CameraOrientationListener(this);
if(myOrientationListener.canDetectOrientation())
myOrientationListener.enable();
}
public static int setCameraDisplayOrientation(Activity activity, int cameraId, Camera camera) {
CameraInfo info = new CameraInfo();
Camera.getCameraInfo(cameraId, info);
int rotation = activity.getWindowManager().getDefaultDisplay().getRotation();
int degrees = 0;
switch (rotation) {
case Surface.ROTATION_0: degrees = 0; break;
case Surface.ROTATION_90: degrees = 90; break;
case Surface.ROTATION_180: degrees = 180; break;
case Surface.ROTATION_270: degrees = 270; break;
}
int result;
if (info.facing == CameraInfo.CAMERA_FACING_FRONT) {
result = (info.orientation + degrees) % 360;
result = (360 - result) % 360; // compensate the mirror
} else { // back-facing
result = (info.orientation - degrees + 360) % 360;
}
camera.setDisplayOrientation(result);
return result;
}
/*
* record the rotation when take photo
*/
public void takePhoto(){
myOrientationListener.rememberOrientation();
rotation += myOrientationListener.getRememberedOrientation();
rotation = rotation % 360;
mCamera.takePicture(null, null, mPicture);
}
class CameraOrientationListener extends OrientationEventListener {
private int currentNormalizedOrientation;
private int rememberedNormalizedOrientation;
public CameraOrientationListener(Context context) {
super(context, SensorManager.SENSOR_DELAY_NORMAL);
}
@Override
public void onOrientationChanged(int orientation) {
// TODO Auto-generated method stub
if (orientation != ORIENTATION_UNKNOWN) {
currentNormalizedOrientation = normalize(orientation);
}
}
private int normalize(int degrees) {
if (degrees > 315 || degrees <= 45) {
return 0;
}
if (degrees > 45 && degrees <= 135) {
return 90;
}
if (degrees > 135 && degrees <= 225) {
return 180;
}
if (degrees > 225 && degrees <= 315) {
return 270;
}
throw new RuntimeException("The physics as we know them are no more. Watch out for anomalies.");
}
public void rememberOrientation() {
rememberedNormalizedOrientation = currentNormalizedOrientation;
}
public int getRememberedOrientation() {
return rememberedNormalizedOrientation;
}
}
希望能帮助到你:)
Answer 7:
这是使用(下面提到)当你的布局固定在纵向模式下的最佳方法。
@Override
protected void onResume() {
super.onResume();
if (!openCamera(CameraInfo.CAMERA_FACING_BACK)) {
alertCameraDialog();
}
if (cOrientationEventListener == null) {
cOrientationEventListener = new OrientationEventListener(this, SensorManager.SENSOR_DELAY_NORMAL) {
public void onOrientationChanged(int orientation) {
// determine our orientation based on sensor response
int lastOrientation = mOrientation;
if (orientation == ORIENTATION_UNKNOWN) return;
Camera.CameraInfo info =
new android.hardware.Camera.CameraInfo();
android.hardware.Camera.getCameraInfo(cameraId, info);
orientation = (orientation + 45) / 90 * 90;
int rotation = 0;
if (info.facing == CameraInfo.CAMERA_FACING_FRONT) {
rotation = (info.orientation - orientation + 360) % 360;
} else { // back-facing camera
rotation = (info.orientation + orientation) % 360;
}
Parameters params = camera.getParameters();
params.setRotation(rotation);
camera.setParameters(params);
}
};
}
if (cOrientationEventListener.canDetectOrientation()) {
cOrientationEventListener.enable();
}
}
您将使用OrientEventListener和实现这个回调方法。 每当有方向变化。因此您的相机旋转将设置和图像将被旋转时,你会保存onOrientationChanged被调用。
private PictureCallback myPictureCallback_JPG = new PictureCallback()
{
@Override
public void onPictureTaken(byte[] arg0, Camera arg1) {
try {
File pictureFile = getOutputMediaFile();
if (pictureFile == null) {
return;
}
FileOutputStream fos = new FileOutputStream(pictureFile);
fos.write(arg0);
fos.close();
camera.startPreview();
} catch (Exception e) {
e.printStackTrace();
}
}
};
getOutputMediaFile
private static File getOutputMediaFile() {
File mediaStorageDir = new File(
Environment
.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),
"MyCameraApp");
if (!mediaStorageDir.exists()) {
if (!mediaStorageDir.mkdirs()) {
Log.d("MyCameraApp", "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;
}
来源这里
Answer 8:
我使用了新的camera2 API来获取传感器的方向,然后相应地旋转它:
private void detectSensorOrientation()
{
CameraManager manager = (CameraManager) getSystemService(CAMERA_SERVICE);
try
{
for (String cameraId : manager.getCameraIdList())
{
CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraId);
// We don't use a front facing camera in this sample.
Integer facing = characteristics.get(CameraCharacteristics.LENS_FACING);
if (facing != null && facing == CameraCharacteristics.LENS_FACING_FRONT)
{
continue;
}
cameraOrientaion = characteristics.get(CameraCharacteristics.SENSOR_ORIENTATION);
}
} catch (CameraAccessException e)
{
e.printStackTrace();
}
}
然后用cameraOrientation参数的帮助下,我转动我的cameraPhoto:
private void generateRotatedBitmap()
{
if (cameraOrientaion != 0)
{
Matrix matrix = new Matrix();
matrix.postRotate(cameraOrientaion);
rotatedPhoto =
Bitmap.createBitmap(cameraPhoto, 0, 0, cameraPhoto.getWidth(), cameraPhoto.getHeight(),
matrix, true);
cameraPhoto.recycle();
}
}
文章来源: Controlling the camera to take pictures in portrait doesn't rotate the final images