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

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

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

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


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

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

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

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

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

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

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

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

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


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) {

    }
}







相关文章: