自定义简易相机及图片的二次采样
在开发中,APP中经常会有一个这样的一个界面点击照相跳转手机相机界面,但是由于手机型号特别多,由于许多第三方厂商对底层源码做了很多改变,跳转手机系统相机的时候会有出现崩溃、BUG,下面我们可以自己写一个相机,去跳转我们自定义的相机
这里写代码片
xml文件
activity_main.xml
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="拍照"
android:onClick="click1"
android:id="@+id/takepicture"/>
<ImageView
android:layout_width="match_parent"
android:id="@+id/iv"
android:layout_height="match_parent"/>
carera.xml
<Button
android:layout_width="match_parent"
android:text="确定"
android:onClick="onClick"
android:layout_height="wrap_content"/>
<SurfaceView
android:id="@+id/surfaceView"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
MainActivity
照相获得图片有可能会很大 ,或造成OOM(内存溢出)在这里我对图片做了处理进行了二次采样,
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
imageView=(ImageView) findViewById(R.id.iv);
}
public void click1(View view){
Intent intent = new Intent(this,MyCamera.class);
startActivityForResult(intent,100);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode==100&&resultCode==RESULT_OK&&data!=null){
String path = data.getStringExtra("path");
Log.i("自定义标签", "onActivityResult: "+path);
Bitmap bitmap = BitmapFactory.decodeFile(path);
imageView.setImageBitmap(bitmap);
}
}
}
Mycamera
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_camera);
surface = (SurfaceView) findViewById(R.id.surfaceView);
SurfaceHolder holder = surface.getHolder();//获得界面的持有者
holder.addCallback(this);//大的控件初始化需要时间,异步操作
}
public void onClick(View view) {
camera.takePicture(new Camera.ShutterCallback() {
@Override
public void onShutter() {//按下快门
}
}, new Camera.PictureCallback() {
@Override
public void onPictureTaken(byte[] data, Camera camera) {
//返回一张原始图片raw格式
}
}, new Camera.PictureCallback() {
@Override
public void onPictureTaken(byte[] data, Camera camera) {
try {
//返回一张压缩后的图片jpeg,返回的图片有可能还会很大,我们将对他进行二次采样,进行压缩避免OOM(内存溢出)
Matrix m = new Matrix();
m.setRotate(90);
//Bitmap newBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), m, true);
//将图片的名称转换为日期格式
SimpleDateFormat Dataformat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date currentDate = new Date();
String stringDate = Dataformat.format(currentDate);
//将data数组写入到指定路劲下
File file = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM) + "/" + stringDate + ".jpeg");
FileOutputStream fos = new FileOutputStream(file);
fos.write(data,0,data.length);
fos.close();
//获取屏幕的宽高的分辨率
WindowManager manager = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
DisplayMetrics metrics = new DisplayMetrics();
manager.getDefaultDisplay().getMetrics(metrics);
//将图片进行压缩
rarBitmap(file.getAbsolutePath(),metrics.widthPixels,metrics.heightPixels );
Intent intent = new Intent();
intent.putExtra("path", file.getAbsolutePath());
Log.i("自定义标签", "onPictureTaken: " + file.getAbsolutePath());
setResult(RESULT_OK, intent);
finish();
fos.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
});
}
/**
* 压缩图片
*
* @param picPath 原始图片的路径
* @param wandWidth 期望的宽度
* @param wandHeight 期望的高度
* @return
*/
public Bitmap rarBitmap(String picPath, int wandWidth, int wandHeight) {
Bitmap bewBitmap = null;
BitmapFactory.Options ops = new BitmapFactory.Options();//创建图片时候的选项
ops.inJustDecodeBounds = true;//进入仅编码模式,只获取元数据 不真正加载图片
BitmapFactory.decodeFile(picPath, ops);//这行代码执行完毕, 会将图片的元数据放到 ops 里面
int height = ops.outHeight;//获取原始图片的高度
int width = ops.outWidth;//宽度
int scalx = (int) (((float) width) / wandWidth + 0.6f);//计算一个宽度的压缩比
int scaly = (int) (((float) height) / wandHeight + 0.6f);//计算一个高度的压缩比
//因为期望的宽高度的比例 和原始的宽高度可能不一致,所以我们应该以一个方向为准,防止图片压缩后变形,两个压缩值以谁大取谁
int scale = scalx > scaly ? scalx : scaly;
ops.inSampleSize = scale;
//重新加载图片,首先推出仅编码模式
ops.inJustDecodeBounds = false;
bewBitmap = BitmapFactory.decodeFile(picPath, ops);
return bewBitmap;
}
/**
* 在这初始化相机
*
* @param holder
*/
@Override
public void surfaceCreated(SurfaceHolder holder) {
try {
camera = Camera.open();//打开相机
camera.setPreviewDisplay(holder);//设置预览
camera.setDisplayOrientation(90);//因为默认横屏,所以旋转90度
camera.startPreview();//启动预览
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 状态发生了改变
*
* @param holder
* @param format
* @param width
* @param height
*/
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
/**
* 销毁的时候把相机释放掉,要不然别的地方会打不开相机
*
* @param holder
*/
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
camera.release();//释放相机
}
}