canvas 对图片进行涂抹,涂抹区域保存图片存入本地

来源:互联网 发布:分水岭分割算法流程图 编辑:程序博客网 时间:2024/04/29 13:30

今晚写了一个比较有意思的控件 ,也是项目需要,项目做一个OCR的图片识别 ,上午老板提出一个需求 ,增加触摸翻译的功能 。我觉得比较有趣,就画了2个多小时吧这个控件写出来并分享出来,网上搜了一下,目前还没有类似的控件的功能 

代码目前考虑的范围不够全面,等我软件优化完了,这里修复一下,给大家看看思路

后来写了一个升级版的,解决屏幕不适配的问题 :

http://blog.csdn.net/fkgjdkblxckvbxbgb/article/details/77801086


先介绍下百度翻译的OCR功能 :

   1:拍照,拿到照片,识别里面的文字 ,根据识别的文字进行翻译 。

    2:截图翻译,就是根据截取的屏幕内容对内容进行翻译,准确率更高

    3:涂抹翻译,比截图翻译更精确,正对性更强

今天要写的就是第三种 涂抹翻译,原理不难 ,

   有点类似刮刮卡的功能 ,然后涂抹区域的bitmap进行重绘制保存

  先看效果图 ,虚拟机没看不出来效果,需要用真机,因为有用到SD卡读写权限 ,最后返回的是图片的存储路径

我  

我的代码都比较容易看懂 ,没有那么多的嵌套封装,注释的很清楚,


package com.reeman.view;import android.content.Context;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.graphics.Path;import android.graphics.PorterDuff;import android.graphics.PorterDuffXfermode;import android.graphics.RectF;import android.util.AttributeSet;import android.util.Log;import android.view.MotionEvent;import android.view.View;import com.reeman.view.entity.TouchPoint;import java.io.File;import java.io.FileOutputStream;import java.util.ArrayList;import java.util.Collections;import java.util.List;public class XfermodeView extends View {    private Bitmap mBgBitmap;    Bitmap mFgBitmap;    private Paint mPaint;    private Canvas mCanvas;    private Path mPath;    int FINGER_WIDTH = 40;    public XfermodeView(Context context) {        this(context, null);    }    public XfermodeView(Context context, AttributeSet attrs) {        this(context, attrs, 0);    }    public XfermodeView(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);        init();    }    @Override    protected void onDraw(Canvas canvas) {        canvas.drawBitmap(mBgBitmap, 0, 0, null);        canvas.drawBitmap(mFgBitmap, 0, 0, null);    }    private void init() {        mPaint = new Paint();        mPaint.setAlpha(0);        mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));        mPaint.setStyle(Paint.Style.STROKE);        mPaint.setStrokeJoin(Paint.Join.ROUND);        mPaint.setStrokeWidth(80);        mPaint.setStrokeCap(Paint.Cap.ROUND);        mPath = new Path();//        mBgBitmap = BitmapFactory.decodeResource(getResources(), imageId);//        mFgBitmap = Bitmap.createBitmap(mBgBitmap.getWidth(), mBgBitmap.getHeight(), Bitmap.Config.ARGB_8888);//        mCanvas = new Canvas(mFgBitmap);//        mCanvas.drawColor(BLACK_HALF_COLOR);    }    int BLACK_HALF_COLOR = 0x89000000;    float startX, startY, endX, endY;    @Override    public boolean onTouchEvent(MotionEvent event) {        switch (event.getAction()) {            case MotionEvent.ACTION_DOWN:                startX = event.getX();                startY = event.getY();                listPoint.clear();                listPoint.add(new TouchPoint(event.getX(), event.getY()));                Log.i("point", "====添加的点==" + startX + "/" + startY);                mPath.reset();                mPath.moveTo(startX, startY);                break;            case MotionEvent.ACTION_MOVE:                listPoint.add(new TouchPoint(event.getX(), event.getY()));                mPath.lineTo(event.getX(), event.getY());                break;            case MotionEvent.ACTION_UP:                endX = event.getX();                endY = event.getY();                listPoint.add(new TouchPoint(event.getX(), event.getY()));                changePoints();                Log.i("point", "====添加的点==" + endX + "/" + endY);                break;        }        mCanvas.drawPath(mPath, mPaint);        invalidate();        return true;    }    List<TouchPoint> listPoint = new ArrayList<>();    List<Float> pointX = new ArrayList<>();    List<Float> pointY = new ArrayList<>();    /***     * 计算手指滑动的区域     */    private void changePoints() {        pointX.clear();        pointY.clear();        for (int i = 0; i < listPoint.size(); i++) {            pointX.add(listPoint.get(i).getPointX());            pointY.add(listPoint.get(i).getPointY());        }        /***         * 这里因为用户会反复的涂抹,所以吧所有的移动点添加到集合中,然后对所有的点取值         * 取出手指的最大范围和最小范围,         */        float minX = Collections.min(pointX);        float minY = Collections.min(pointY);        float maxX = Collections.max(pointX);        float maxY = Collections.max(pointY);        /***         * 这里加上笔触的宽度         */        minX = minX - FINGER_WIDTH;        minY = minY - FINGER_WIDTH;        maxX = maxX + FINGER_WIDTH;        maxY = maxY + FINGER_WIDTH;        if (minX < 0) {            minX = 0;        }        if (minY < 0) {            minY = 0;        }        if (maxX > MainActivity.width) {            maxX = MainActivity.width;        }        if (maxY > MainActivity.height) {            maxY = MainActivity.height;        }        //这是手指绘制的区域        RectF rect = new RectF(minX, minY, maxX, maxY);        saveBitmap(rect);    }    /***     * 保存图片到本地     * @param rect     */    private void saveBitmap(RectF rect) {        try {            Log.i("point", "====保存的尺寸==" + rect.left + "/" + rect.top + "  ///" + rect.right + "/" + rect.bottom);            Bitmap bmp = Bitmap.createBitmap((int) rect.width(), (int) rect.height(), Bitmap.Config.ARGB_8888);            Canvas canvas = new Canvas(bmp);            canvas.translate(-(rect.left), -(rect.top));            canvas.drawColor(Color.WHITE);            canvas.drawBitmap(mBgBitmap, 0, 0, null);            canvas.save(Canvas.ALL_SAVE_FLAG);            canvas.restore();            File file = new File("/sdcard//test.png");            if (!file.exists()) {                file.createNewFile();            }            FileOutputStream fos = new FileOutputStream(file.getPath());            bmp.compress(Bitmap.CompressFormat.PNG, 100, fos);            fos.close();            listener.touchBackUrl(file.getPath());        } catch (Exception e) {            listener.touchCutError(e.toString());            e.printStackTrace();        }    }    public void translateImage(int imageId) {        mBgBitmap = BitmapFactory.decodeResource(getResources(), imageId);        mFgBitmap = Bitmap.createBitmap(mBgBitmap.getWidth(), mBgBitmap.getHeight(), Bitmap.Config.ARGB_8888);        mCanvas = new Canvas(mFgBitmap);        mCanvas.drawColor(BLACK_HALF_COLOR);    }    TouchCutListener listener;    public void setOnTouchCutListener(TouchCutListener listener) {        this.listener = listener;    }    public interface TouchCutListener {        //        void touchPoint(float left, float top, float right, float bottom);        void touchBackUrl(String filePath);        void touchCutError(String error);    }}

布局代码,切记,用真机看效果,虚拟机看不到效果

<?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"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    tools:context="com.reeman.view.MainActivity">    <RelativeLayout        android:layout_width="match_parent"        android:layout_height="150dp"        android:background="@color/colorAccent">        <ImageView            android:id="@+id/iv_bitma"            android:layout_width="300dp"            android:layout_height="150dp" />    </RelativeLayout>    <com.reeman.view.XfermodeView        android:id="@+id/modeview"        android:layout_width="300dp"        android:layout_height="300dp"        android:layout_alignParentBottom="true"        android:layout_centerInParent="true" /></RelativeLayout>


主界面代码,为什么要使用真机测试,主界面代码一目了然

package com.reeman.view;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.os.Bundle;import android.support.v7.app.AppCompatActivity;import android.view.WindowManager;import android.widget.ImageView;public class MainActivity extends AppCompatActivity implements XfermodeView.TouchCutListener {    static int width;    static int height;    XfermodeView modeview;    private ImageView iv_bitma;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        WindowManager wm = this.getWindowManager();        width = wm.getDefaultDisplay().getWidth();        height = wm.getDefaultDisplay().getHeight();        setContentView(R.layout.activity_main);        iv_bitma = (ImageView) findViewById(R.id.iv_bitma);        modeview = (XfermodeView) findViewById(R.id.modeview);        modeview.translateImage(R.mipmap.test5);        modeview.setOnTouchCutListener(this);    }    @Override    public void touchBackUrl(String filePath) {        Bitmap map = BitmapFactory.decodeFile(filePath);        iv_bitma.setImageBitmap(map);    }    @Override    public void touchCutError(String error) {    }}