方便以后修改
package com.example.coreviewtest;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.List;
import android.app.Activity;
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.graphics.PixelFormat;
import android.hardware.Camera;
import android.hardware.Camera.AutoFocusCallback;
import android.hardware.Camera.CameraInfo;
import android.hardware.Camera.PictureCallback;
import android.hardware.Camera.PreviewCallback;
import android.hardware.Camera.ShutterCallback;
import android.hardware.Camera.Size;
import android.util.AttributeSet;
import android.util.Log;
import android.view.Display;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.WindowManager;
import android.widget.Toast;
/**
* 自定义照相机 用法:直接在布局中设置该View 调用takePicture方法实现拍照 调用savePicture方法实现保存拍照后的图片
* 调用cancle方法实现重拍 调用rotateCamera方法实现前后置镜头的切换 bug to fix:after save the
* picture,the picture rotate(sonyLT26i:font camera:90,back camera:-90)
*
* @author ebirdfighter
*/
public class MySurfaceView extends SurfaceView implements
SurfaceHolder.Callback {
SurfaceHolder mHolder;
Camera mCamera;
final String ORIENTATION = "orientation";
final String PORTRAIT = "portrait";
final String LANDSCAPE = "landscape";
private final int BITMAP_LIMIT_MEMORY = 100;// save bitmap size limit in
// 100kb
private final String BITMAP_SAVE_PATH = "/sdcard/test.jpg";
private boolean mCanClick = true;
private byte[] mCurrentBMData = null;
private String SAVE_SUCEESS = "保存成功";
private String CAN_DO_BEFORE_CANCLE_OR_SAVE = "请选择保存或取消后再拍照";
private Boolean mIsFront = false;
private final int CAMERA_DEFAULT_ID = -1;
private int mFrontCameraId = CAMERA_DEFAULT_ID;
private int mBackCameraId = CAMERA_DEFAULT_ID;
public MySurfaceView(Context context) {
super(context);
init(context);
}
public MySurfaceView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
public MySurfaceView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context);
}
private void init(Context context) {
mHolder = getHolder();
mHolder.addCallback(this);
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
startPreview();
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
if (mCamera != null) {
Camera.Parameters parameters = mCamera.getParameters();
Size size = parameters.getPictureSize();
List<Size> sizes = parameters.getSupportedPreviewSizes();
Size optimalSize = getOptimalPreviewSize(sizes, (double) size.width
/ size.height);
if (optimalSize != null) {
parameters
.setPreviewSize(optimalSize.width, optimalSize.height);
Log.i("getOptimalPreviewSize", "" + optimalSize.width + " "
+ optimalSize.height);
}
mCamera.setParameters(parameters);
}
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
stopPreview();
}
Camera.PreviewCallback mPreviewCallback = new PreviewCallback() {
@Override
public void onPreviewFrame(byte[] data, Camera camera) {
}
};
Camera.AutoFocusCallback autoFocusCallback = new AutoFocusCallback() {
@Override
public void onAutoFocus(boolean success, Camera camera) {
if (success || mIsFront) {
mCamera.takePicture(null, null, jpeg);
}
}
};
// add the sound when takePicture
private ShutterCallback shutterCallback = new ShutterCallback() {
@Override
public void onShutter() {
}
};
private PictureCallback raw = new PictureCallback() {
@Override
public void onPictureTaken(byte[] data, Camera camera) {
}
};
private PictureCallback jpeg = new PictureCallback() {
@Override
public void onPictureTaken(byte[] data, Camera camera) {
mCurrentBMData = data;// save newst data
stopPreview();
}
};
public void savePicture() {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
options.inPreferredConfig = Config.ARGB_8888;// declare each pixel is
// stored on 4 bytes
BitmapFactory.decodeByteArray(mCurrentBMData, 0, mCurrentBMData.length,
options);
int bitmapMemSize = options.outHeight * options.outWidth * 4 / 8 / 1024;
int sampleSize = 1;
while (bitmapMemSize / (sampleSize * sampleSize) > BITMAP_LIMIT_MEMORY) {
sampleSize++;
}
options.inJustDecodeBounds = false;
options.inSampleSize = sampleSize;
Bitmap bitmap = BitmapFactory.decodeByteArray(mCurrentBMData, 0,
mCurrentBMData.length, options);
bitmap = rotateBitmap(bitmap, 90);
File file = new File(BITMAP_SAVE_PATH);
try {
BufferedOutputStream bos = new BufferedOutputStream(
new FileOutputStream(file));
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, bos);
bos.flush();
bos.close();
} catch (Exception e) {
e.printStackTrace();
}
Toast.makeText(getContext(), SAVE_SUCEESS, Toast.LENGTH_SHORT).show();
startPreview();
}
private Bitmap rotateBitmap(Bitmap src, int degrees) {
Matrix matrix = new Matrix();
matrix.reset();
matrix.setRotate(degrees);
Bitmap dstBitmap = Bitmap.createBitmap(src, 0, 0, src.getWidth(),
src.getHeight(), matrix, true);
src.recycle();
return dstBitmap;
}
public void takePicture() {
if (mCanClick) {
mCanClick = false;
mCamera.autoFocus(autoFocusCallback);
} else {
Toast.makeText(getContext(), CAN_DO_BEFORE_CANCLE_OR_SAVE,
Toast.LENGTH_SHORT).show();
}
}
public void cancle() {
startPreview();
}
public void startPreview() {
if (mCamera != null) {
mCamera.startPreview();
} else {
if (mIsFront) {
if (mFrontCameraId != CAMERA_DEFAULT_ID) {
openCamera(mFrontCameraId);
} else {
}
} else {
if (mBackCameraId != CAMERA_DEFAULT_ID) {
openCamera(mBackCameraId);
} else {
openBackCamera();
}
}
}
mCanClick = true;
}
public void stopPreview() {
if (mCamera != null) {
mCamera.setPreviewCallback(null);
mCamera.stopPreview();
mCamera.release();
mCamera = null;
mCanClick = false;
}
}
public void rotateCamera() {
mIsFront = !mIsFront;
if (mIsFront) {
if (mFrontCameraId != CAMERA_DEFAULT_ID) {
openCamera(mFrontCameraId);
return;
}
} else {
if (mBackCameraId != CAMERA_DEFAULT_ID) {
openCamera(mBackCameraId);
return;
}
}
// call once at most,to get value of mFrontCameraId and mBackCameraId
if (mIsFront) {
openFrontCamera();
} else {
openBackCamera();
}
}
private void openFrontCamera() {
int cameraCount = 0;
CameraInfo cameraInfo = new CameraInfo();
cameraCount = Camera.getNumberOfCameras();
for (int i = 0; i < cameraCount; i++) {
Camera.getCameraInfo(i, cameraInfo);
if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
openCamera(i);
mFrontCameraId = i;
break;
}
}
}
private void openBackCamera() {
int cameraCount = 0;
CameraInfo cameraInfo = new CameraInfo();
cameraCount = Camera.getNumberOfCameras();
for (int i = 0; i < cameraCount; i++) {
Camera.getCameraInfo(i, cameraInfo);
if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_BACK) {
openCamera(i);
mBackCameraId = i;
break;
}
}
}
public void openCamera(int index) {
stopPreview();
mCamera = Camera.open(index);
try {
Camera.Parameters parameters = mCamera.getParameters();
parameters.setPictureFormat(PixelFormat.JPEG); // Sets the image format for picture
parameters.setPreviewFormat(PixelFormat.YCbCr_420_SP); // Sets the image format for preview picture,默认为NV21
if (getResources().getConfiguration().orientation != Configuration.ORIENTATION_LANDSCAPE) {
parameters.set(ORIENTATION, PORTRAIT);
mCamera.setDisplayOrientation(90);// useful above 2.2
parameters.setRotation(90);
} else {
parameters.set(ORIENTATION, LANDSCAPE);
mCamera.setDisplayOrientation(0);// useful above 2.2
parameters.setRotation(0);
}
mCamera.setParameters(parameters);
mCamera.setPreviewDisplay(mHolder);
mCamera.startPreview();
mCamera.setPreviewCallback(mPreviewCallback);
} catch (IOException e) {
e.printStackTrace();
}
mCanClick = true;
}
private Size getOptimalPreviewSize(List<Size> sizes, double targetRatio) {
final double ASPECT_TOLERANCE = 0.05;
if (sizes == null)
return null;
Size optimalSize = null;
double minDiff = Double.MAX_VALUE;
// Because of bugs of overlay and layout, we sometimes will try to
// layout the viewfinder in the portrait orientation and thus get the
// wrong size of mSurfaceView. When we change the preview size, the
// new overlay will be created before the old one closed, which causes
// an exception. For now, just get the screen size
Display display = ((Activity) getContext()).getWindowManager()
.getDefaultDisplay();
int targetHeight = Math.max(display.getHeight(), display.getWidth());
if (targetHeight <= 0) {
// We don't know the size of SurefaceView, use screen height
WindowManager windowManager = (WindowManager) getContext()
.getSystemService(Context.WINDOW_SERVICE);
targetHeight = windowManager.getDefaultDisplay().getHeight();
}
// 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;
}
}
本文详细介绍了如何在Android应用中自定义相机功能,包括拍照、保存照片及前后置镜头切换,并讨论了图像处理技术在拍照后的应用。

1万+

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



