我正在尝试使用Camera类和SurfaceView来实现自定义相机。但相机拍摄的图像会旋转。 SurfaceView中的预览也在旋转,但在代码中我使用 setCameraDisplayOrientation()方法修复了它。下面是在屏幕和图像中生成的图像。我拍了截图。
我正在使用的代码是:
public class CustomCameraActivity extends AppCompatActivity implements PictureCallback, SurfaceHolder.Callback
{
private Camera mCamera;
private ImageView mCameraImage;
private SurfaceView mCameraPreview;
private Button mCaptureImageButton;
private byte[] mCameraData;
private boolean mIsCapturing;
private OnClickListener mCaptureImageButtonClickListener = new OnClickListener() {
@Override
public void onClick(View v) {
App.getInstance().setCapturedPhotoData(null);
captureImage();
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_custom_camera);
mImgViewCover = (ImageView) findViewById(R.id.imgVw_customCameraCover);
mCameraImage = (ImageView) findViewById(R.id.camera_image_view);
mCameraImage.setVisibility(View.INVISIBLE);
mCameraPreview = (SurfaceView) findViewById(R.id.preview_view);
final SurfaceHolder surfaceHolder = mCameraPreview.getHolder();
surfaceHolder.addCallback(this);
if(Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB)
surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
mCaptureImageButton = (Button) findViewById(R.id.capture_image_button);
mCaptureImageButton.setOnClickListener(mCaptureImageButtonClickListener);
mIsCapturing = true;
}
@Override
protected void onResume() {
super.onResume();
if (mCamera == null) {
try {
mCamera = Camera.open();
mCamera.setPreviewDisplay(mCameraPreview.getHolder());
if (mIsCapturing) {
mCamera.startPreview();
}
} catch (Exception e) {
Toast.makeText(CustomCameraActivity.this, "Unable to open camera.", Toast.LENGTH_LONG)
.show();
}
}
}
@Override
protected void onPause() {
super.onPause();
if (mCamera != null) {
mCamera.release();
mCamera = null;
}
}
@Override
public void onPictureTaken(byte[] data, Camera camera) {
mCameraData = data;
setupImageDisplay();
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
if (holder.getSurface() == null)
return;
try { mCamera.stopPreview();
} catch (Exception e) { }
if (mCamera != null) {
try {
Camera.Parameters parameters = mCamera.getParameters();
List<Size> sizes = parameters.getSupportedPreviewSizes();
Size optimalSize = getOptimalPreviewSize(sizes, width, height);
parameters.setPreviewSize(optimalSize.width, optimalSize.height);
mCamera.setParameters(parameters);
setCameraDisplayOrientation(this, Camera.CameraInfo.CAMERA_FACING_BACK, mCamera );
if (mIsCapturing) {
mCamera.startPreview();
}
} catch (Exception e) {
Toast.makeText(CustomCameraActivity.this, "Unable to start camera preview.", Toast.LENGTH_LONG).show();
}
}
}
@Override
public void surfaceCreated(SurfaceHolder holder)
{
try {
mCamera = Camera.open();
mCamera.setPreviewDisplay(holder);
} catch (IOException exception) {
mCamera.release();
mCamera = null;
}
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
if (mCamera != null)
{ mCamera.stopPreview();
mCamera.release();
mCamera = null;}
}
private void captureImage() {
mCamera.takePicture(null, null, this);
}
private void setupImageCapture() {
mCameraImage.setVisibility(View.INVISIBLE);
mCameraPreview.setVisibility(View.VISIBLE);
mCamera.startPreview();
mCaptureImageButton.setText("capture image");
mCaptureImageButton.setOnClickListener(mCaptureImageButtonClickListener);
}
private void setupImageDisplay() {
Bitmap bitmap = BitmapFactory.decodeByteArray(mCameraData, 0, mCameraData.length);
mCameraImage.setImageBitmap(bitmap);
mCamera.stopPreview();
mCameraPreview.setVisibility(View.INVISIBLE);
mCameraImage.setVisibility(View.VISIBLE);
if (mCameraData != null) {
Intent intent = new Intent();
intent.putExtra(EXTRA_CAMERA_DATA, mCameraData);
setResult(RESULT_OK, intent);
} else {
setResult(RESULT_CANCELED);
}
}
private Size getOptimalPreviewSize(List<Size> sizes, int w, int h) {
final double ASPECT_TOLERANCE = 0.5;
double targetRatio = (double) w / h;
if (sizes == null) return null;
Size optimalSize = null;
double minDiff = Double.MAX_VALUE;
int targetHeight = h;
// Try to find an size match aspect ratio and size
for (Size size : sizes) {
double ratio = (double) size.width / size.height;
if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE) continue;
if (Math.abs(size.height - targetHeight) < minDiff) {
optimalSize = size;
minDiff = Math.abs(size.height - targetHeight);
}
}
// Cannot find the one match the aspect ratio, ignore the requirement
if (optimalSize == null) {
minDiff = Double.MAX_VALUE;
for (Size size : sizes) {
if (Math.abs(size.height - targetHeight) < minDiff) {
optimalSize = size;
minDiff = Math.abs(size.height - targetHeight);
}
}
}
return optimalSize;
}
public static void setCameraDisplayOrientation(Context context,
int cameraId, android.hardware.Camera camera) {
android.hardware.Camera.CameraInfo info =
new android.hardware.Camera.CameraInfo();
android.hardware.Camera.getCameraInfo(cameraId, info);
int rotation = ((Activity)context).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);
// camera.getParameters().setRotation(result);
}
}
我可以在使用代码显示之前将位图旋转到90,然后使用代码:
public static Bitmap rotateImage(Bitmap img, int degree) {
Matrix matrix = new Matrix();
matrix.postRotate(degree);
Bitmap rotatedImg = Bitmap.createBitmap(img, 0, 0, img.getWidth(), img.getHeight(), matrix, true);
img.recycle();
return rotatedImg;
}
但它不应该是解决问题的正确方法。那么,我该如何修复它并在imageView中显示非旋转图像?
答案 0 :(得分:1)
使用这种方式使用表面视图Java代码
打开相机public class CameraOverlayActivity extends AppCompatActivity implements SurfaceHolder.Callback {
Camera camera;
SurfaceView surfaceView;
SurfaceHolder surfaceHolder;
boolean previewing = false;
LayoutInflater controlInflater = null;
private File videoPath;
private ImageView imgCapture;
int camBackId;
String strVideoFolderPath;
private ProgressDialog progressDialog;
Camera.Parameters parameters;
public boolean hasFlash;
public boolean camRotation = false;
private RelativeLayout relativeLayout;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_camera_overlay);
relativeLayout = findViewById(R.id.control);
camBackId = Camera.CameraInfo.CAMERA_FACING_BACK;
hasFlash = this.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA_FLASH);
surfaceView = findViewById(R.id.surface);
progressDialog = new ProgressDialog(this);
progressDialog.setTitle(null);
progressDialog.setCancelable(false);
surfaceHolder = surfaceView.getHolder();
surfaceHolder.addCallback(this);
strVideoFolderPath = Environment.getExternalStorageDirectory().getAbsolutePath();
surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
controlInflater = LayoutInflater.from(getBaseContext());
videoPath = new File(Environment.getExternalStorageDirectory() + "/sw/raw");
if (videoPath.exists()) {
if (videoPath.isDirectory()) {
if (videoPath.listFiles().length != 0) {
String[] children = videoPath.list();
for (int i = 0; i < children.length; i++) {
new File(videoPath, children[i]).delete();
}
}
}
}
if (!videoPath.exists()) {
videoPath.mkdirs();
}
imgCapture = findViewById(R.id.img_capture);
imgCapture.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (camera != null) {
if (previewing) {
System.gc();
try {
capturePhoto();
} catch (Exception e) {
Log.v("ERRORR", e.getMessage());
e.printStackTrace();
}
}
}
}
});
}
public void capturePhoto() throws Exception {
camera.takePicture(null, null, myPictureCallback_JPG);
}
@Override
protected void onResume() {
super.onResume();
Display display = ((WindowManager) getSystemService(WINDOW_SERVICE)).getDefaultDisplay();
}
Camera.PictureCallback myPictureCallback_JPG = new Camera.PictureCallback() {
@Override
public void onPictureTaken(byte[] arg0, Camera arg1) {
// TODO Auto-generated method stub
FileOutputStream outStream = null;
//camera.startPreview();
try {
Date date = new Date();
String filename = "/rec" + date.toString().replace(" ", "_").replace(":", "_") + ".jpg";
filename = filename.replace("+", "");
File file = new File(Environment.getExternalStorageDirectory() + "/Switch It");
if (!file.exists())
file.mkdirs();
outStream = new FileOutputStream(file + filename);
outStream.write(arg0);
outStream.close();
Log.v("File_Path", file.getAbsolutePath());
Intent returnIntent = new Intent();
returnIntent.putExtra("img_capture", file.getAbsolutePath() + filename);
setResult(Activity.RESULT_OK, returnIntent);
finish();
} catch (FileNotFoundException e) {
Log.e("ERROR 1", e.getMessage());
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
Log.e("ERROR 2", e.getMessage());
} finally {
}
}
};
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
// TODO Auto-generated method stub
if (previewing) {
camera.stopPreview();
previewing = false;
}
if (camera != null) {
try {
camera.setPreviewDisplay(surfaceHolder);
parameters = camera.getParameters();
if (getPackageManager().hasSystemFeature("android.hardware.camera.autofocus")) {
parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
}
camera.startPreview();
if (hasFlash) {
parameters.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
}
camera.setParameters(parameters);
previewing = true;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
// TODO Auto-generated method stub
camera = Camera.open();
if (android.os.Build.VERSION.SDK_INT > 7) {
Display display = ((WindowManager) getSystemService(WINDOW_SERVICE)).getDefaultDisplay();
if (display.getRotation() == Surface.ROTATION_0) {
camera.setDisplayOrientation(90);
camRotation = true;
}
}
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
// TODO Auto-generated method stub
if (camera != null) {
camera.stopPreview();
camera.release();
camera = null;
previewing = false;
}
}
}
答案 1 :(得分:0)
根据您的要求旋转图像时,只需旋转imageview
角度您可以旋转ImageView
使用此
mImageView.setRotation(yourRequiredAngle)
希望它有所帮助。