android自定义相机添加蒙板,拍照剪切

前几天,我写了一篇自定义相机加取景框的文章,这几天,我又研究了一下,进一步写了蒙板,并且拍照出来剪切只留取景框的照片。

加上对之前代码的调整。现在又记录下来

现在的效果是这样的

布局文件

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <FrameLayout
        android:id="@+id/myFramelayout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <SurfaceView
            android:id="@+id/surfaceView"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical">

            <TextView
                android:id="@+id/view1"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:background="#FFFFFF"
                android:gravity="center_horizontal"
                android:text="\n请将方框对准证件拍摄"
                android:textSize="18dp"
                android:textColor="@color/colorAccent"
                android:alpha="0.6"/>

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:orientation="horizontal">

                <View
                    android:id="@+id/view2"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:background="#FFFFFF"
                    android:alpha="0.6"/>

                <com.example.administrator.myapplication.MyView
                    android:id="@+id/myView"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_gravity="center" />

                <View
                    android:id="@+id/view3"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:background="#FFFFFF"
                    android:alpha="0.6"/>
            </LinearLayout>

            <View
                android:id="@+id/view4"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:background="#FFFFFF"
                android:alpha="0.6"/>

        </LinearLayout>
    </FrameLayout>

    <LinearLayout
        android:id="@+id/linear"
        android:layout_width="55dp"
        android:layout_height="match_parent"
        android:layout_alignParentRight="true"
        android:layout_marginRight="8dp"
        android:gravity="center_vertical">

        <Button
            android:id="@+id/takepicture_button"
            android:layout_width="50dp"
            android:layout_height="50dp"
            android:background="@mipmap/xiang_ji"
            android:onClick="takepicture" />

    </LinearLayout>

</RelativeLayout>
自定义MyView,这次MyView对于算取景框的线是灵活的,更改参数可以调整取景框的大小,并且取景框线也跟着移动

public class MyView extends View {

        //获取屏幕的宽和高。根据屏幕的宽和高来算取景框的位置
    private int screenWidth, screenHeight, myViewPaddingLeft, myViewPaddingTop;
        private int  langLine = 100, //取景框长线的长度
              shortLine = 50, //取景框线的长度
              origin = 0;//原点

    public MyView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public void setMyParams(int screenWidth, int screenHeight, int myViewPaddingLeft, int myViewPaddingTop) {
        this.screenWidth = screenWidth;
        this.screenHeight = screenHeight;
        this.myViewPaddingLeft = myViewPaddingLeft;
        this.myViewPaddingTop = myViewPaddingTop;
    }

    @Override
    public void onDraw(Canvas canvas) {
        Paint paint = new Paint();
        paint.setColor(Color.RED);
        paint.setAlpha(250);
        paint.setAntiAlias(true);
        paint.setStyle(Paint.Style.STROKE);
        paint.setStrokeWidth(5);
        // 下面是取景框的8条线
    // xy的算法是:把屏幕横着(逆时针旋转90度的屏幕),相对这个view来讲(左上角是原点0,0),从左到右是x轴,从上到下是y
        //左上角两条线
    canvas.drawLine(origin, origin, langLine, origin, paint);
        canvas.drawLine(origin, origin, origin, shortLine, paint);
        //左下角两条线
    canvas.drawLine(origin, screenHeight - myViewPaddingTop, langLine, screenHeight - myViewPaddingTop, paint);
        canvas.drawLine(origin, screenHeight - myViewPaddingTop, origin, screenHeight - myViewPaddingTop - shortLine, paint);
        //右上角两条线
    canvas.drawLine(screenWidth - myViewPaddingLeft, origin, screenWidth - myViewPaddingLeft - langLine, origin, paint);
        canvas.drawLine(screenWidth - myViewPaddingLeft, origin, screenWidth - myViewPaddingLeft, shortLine, paint);
        //右下角两条线
    canvas.drawLine(screenWidth - myViewPaddingLeft, screenHeight - myViewPaddingTop, screenWidth - myViewPaddingLeft - langLine, screenHeight - myViewPaddingTop, paint);
        canvas.drawLine(screenWidth - myViewPaddingLeft, screenHeight - myViewPaddingTop, screenWidth - myViewPaddingLeft, screenHeight - myViewPaddingTop - shortLine, paint);
        super.onDraw(canvas);
    }
}
最后是Acvitity代码

    private MyView myView;
    private View view2, view3, view4;//3个蒙板
  private TextView view1;//1个蒙板
    private Camera camera;
private Button takepicture_button ; private SurfaceView surfaceview ; private int screenWidth , screenHeight ; private int myViewPaddingLeft = 500 , //MyView 左右距离屏幕的距离(意思是 MyView 左右两边一共空了 500 myViewPaddingTop = 300 ; //MyView 上下距离屏幕的距离(意思是 MyView 上下两边一共空了 500
    private ToneGenerator tone;
  private Camera.AutoFocusCallback myAutoFocusCallback = new Camera.AutoFocusCallback() { @Override public void onAutoFocus( boolean success , Camera camera) { Log. w( "print" , " 聚焦完成,,,, ") ; // 聚焦后发出提示音 tone = new ToneGenerator(AudioManager. STREAM_MUSIC ,ToneGenerator. MAX_VOLUME) ; tone.startTone(ToneGenerator. TONE_PROP_BEEP2) ; } } ; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState) ; setRequestedOrientation(ActivityInfo. SCREEN_ORIENTATION_LANDSCAPE) ; // 把屏幕设置成横屏 setContentView(R.layout. test_layout) ; WindowManager wm = (WindowManager) this.getSystemService(Context. WINDOW_SERVICE) ; screenWidth = wm.getDefaultDisplay().getWidth() ; screenHeight = wm.getDefaultDisplay().getHeight() ; view1 = (TextView) findViewById(R.id. view1) ; LinearLayout.LayoutParams layoutParams1 = (LinearLayout.LayoutParams) view1.getLayoutParams() ; layoutParams1. height = myViewPaddingTop / 2 ; view1.setLayoutParams(layoutParams1) ; myView = (MyView) findViewById(R.id. myView) ; myView.setMyParams( screenWidth , screenHeight , myViewPaddingLeft , myViewPaddingTop) ; LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) myView.getLayoutParams() ; layoutParams. width = screenWidth - myViewPaddingLeft ; layoutParams. height = screenHeight - myViewPaddingTop ; myView.setLayoutParams(layoutParams) ; view2 = findViewById(R.id. view2) ; LinearLayout.LayoutParams layoutParams2 = (LinearLayout.LayoutParams) view2.getLayoutParams() ; layoutParams2. width = myViewPaddingLeft / 2 ; layoutParams2. height = screenHeight - myViewPaddingTop ; view2.setLayoutParams(layoutParams2) ; view3 = findViewById(R.id. view3) ; LinearLayout.LayoutParams layoutParams3 = (LinearLayout.LayoutParams) view3.getLayoutParams() ; layoutParams3. width = myViewPaddingLeft / 2 ; layoutParams3. height = screenHeight - myViewPaddingTop ; view3.setLayoutParams(layoutParams3) ; view4 = findViewById(R.id. view4) ; LinearLayout.LayoutParams layoutParams4 = (LinearLayout.LayoutParams) view4.getLayoutParams() ; layoutParams4. height = myViewPaddingTop / 2 ; view4.setLayoutParams(layoutParams4) ; surfaceview = (SurfaceView) findViewById(R.id. surfaceView) ; myView.setOnTouchListener( new View.OnTouchListener() { @Override public boolean onTouch(View v , MotionEvent event) { camera.autoFocus( myAutoFocusCallback) ; return false; } }) ; getWindow().setFlags(WindowManager.LayoutParams. FLAG_FULLSCREEN , WindowManager.LayoutParams. FLAG_FULLSCREEN) ; SurfaceHolder holder = surfaceview.getHolder() ; holder.setKeepScreenOn( true) ; // 屏幕常亮 holder.setType(SurfaceHolder. SURFACE_TYPE_NORMAL) ; holder.addCallback( new MySurfaceCallback()) ; holder.lockCanvas() ; } private final class MySurfaceCallback implements Callback { @Override public void surfaceChanged(SurfaceHolder holder , int format , int width , int height) { // surface 的格式或大小发生改变,这个方法就被调用 } @Override public void surfaceCreated(SurfaceHolder holder) { try { camera = Camera. open() ; Camera.Parameters params = camera.getParameters() ; camera.setPreviewDisplay( surfaceview.getHolder()) ; // 开启预览 camera.startPreview() ; } catch (IOException e) { e.printStackTrace() ; } } @Override public void surfaceDestroyed(SurfaceHolder holder) { if ( camera != null) { camera.release() ; camera = null; } } } public void takepicture(View v) { camera.takePicture( mShutterCallback , null,mPicture Callback) ; }
    Camera.ShutterCallback mShutterCallback = new Camera.ShutterCallback(){
public void onShutter() { } } ; private Camera.PictureCallback mPictureCallback = new Camera.PictureCallback() { @Override public void onPictureTaken( byte[] data , Camera camera) { Bitmap mBitmap = BitmapFactory. decodeByteArray(data , 0 , data. length) ; Bitmap mBitmapCut = ImageCrop(mBitmap) ; String rootPath = Environment. getExternalStorageDirectory().toString() + File. separator ; File file = new File(rootPath + System. currentTimeMillis() + ".jpg") ; try { file.createNewFile() ; BufferedOutputStream os = new BufferedOutputStream( new FileOutputStream(file)) ; mBitmapCut.compress(Bitmap.CompressFormat. JPEG , 100 , os) ; //100 是压缩率,100表示 不压缩 os.flush() ; os.close() ; Toast. makeText(getApplicationContext() , " 保存成功 " , Toast. LENGTH_SHORT).show() ; } catch (IOException e) { e.printStackTrace() ; } } } ; /** * 按图片比例裁切图片 */ public Bitmap ImageCrop(Bitmap bitmap) { int w = bitmap.getWidth() ; // 得到图片的宽,高 int h = bitmap.getHeight() ; // 剪切的初始 xy 位置,原点位置 都是根据比例来算的 int x = ( int) ((w * ( myViewPaddingLeft / 2)) / screenWidth) ; int y = ( int) (h * ( myViewPaddingTop / 2) / screenHeight) ; // 剪切的宽和高 int retX = ( int) ((w * ( screenWidth - myViewPaddingLeft)) / screenWidth) ; int retY = ( int) (h * ( screenHeight - myViewPaddingTop) / screenHeight) ; // 必须 x+retX 要小于或等于 bitmap.getWidth() y+retY 要小于或等于 bitmap.getHeight(),不然会报错 return Bitmap. createBitmap(bitmap , x , y , retX , retY , null, false) ; } 最后放上一张保存下来,剪切后的照片,看看效果

如有不妥之处,请大家指正!!

猜你喜欢

转载自blog.csdn.net/ming_csdn_/article/details/70154381