canvas 对图片进行涂抹,涂抹区域保存图片存入本地
今晚写了一个比较有意思的控件 ,也是项目需要,项目做一个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) {} }
canvas 对图片进行涂抹,涂抹区域保存图片存入本地相关推荐
- 小程序画布插入证件照换低并保存图片到本地相册(注意必须保证canvas绘制完成才导出图片)
这里是将证件照图片写死,背景颜色写死,尺寸写死,大家可按需进行改进 首先最注意的地方是保存图片时,必须保证canvas绘制完成 官网教程(最好是配合来看) 第一步:在 WXML 中添加 canvas ...
- 使用canvas对图片进行裁切
canvas canvas 又叫做画布,是 HTML5 新增内容,可以使用js脚本在其中绘制图像的元素. 常用于制作网页上的一些毕竟炫酷的前端特效. 可以完成图片处理.动画渲染.图表渲染等操作. 最近 ...
- vue保存图片到本地
首先呢我们要,安装一下依赖: npm install html2canvas --save 接下来我们就直接上代码了 <van-tab title="签到二维码">&l ...
- IOS15保存图片至本地相机胶卷
IOS15保存图片至本地相机胶卷 主要源码在这: #import "ViewController.h" #define imageURL @"https://wx4.si ...
- url抓取图片存入本地 c#
一:url抓取图片存入本地 c# 二:将图片和文字存入PDF c# 给大家提供程序下载地址:https://download.csdn.net/download/us2019/12888680 将u ...
- iOS 使用钥匙串将用户密码存入本地
在 iOS 开发中,用户一般注册时候,APP会将用户的用户名和密码直接保存到本地,便于用户下次直接进行登录. 这样就会牵扯到一个问题,用户的密码不能以明文的形式存储在本地,使用钥匙串进行保存用户的密码 ...
- 捕获Camera并保存图片到本地(照相功能) -samhy
Flex博文 捕获Camera并保存图片到本地(照相功能) -samhy 作者:admin 日期:2010-07-12 字体大小: 小 中 大 捕获Camera并保存图片到本地(照相功能) 这几天对C ...
- scrapy python3.8_银狐DevNet-网络运维Python初篇(四)netmiko抓取华为网络配置并存入本地...
1.训练场景:读取excel中设备IP地址,通过Netmiko抓取设备配置,并存入本地 上一小节我们通过excel得到设备IP地址,并用Netmiko批量抓取设备配置并打印出来,真实运维场景我们需要把 ...
- 将CSDN600W用户及密码帐号存入本地MySql数据库
有感于密码文本文件太大,索性将其存入本地MySql,其中有6个账户因为文件编码问题不知密码,将其删去. 1 import java.io.BufferedReader; 2 import java. ...
- python save保存图片到本地_python爬取网站上的图片并保存到本地
1.导入需要的模块requests,BeautifulSoup,os(用于文件读写). 2.创建一个类,并初始化. class BeautifulPicture: def __init__(self) ...
最新文章
- pdo mysql bindparam_pdo连接mysql prepare,bindParam插入数据
- vnc用户名 查看linux_linux 查看vnc服务器
- Linux ps aux指令詳解--转
- android跑步软件,手机跑步软件哪个好_安卓手机跑步记录软件_手机跑步app【最新】-太平洋电脑网...
- DDD理论学习系列(12)-- 仓储
- Node.js 应用故障排查手册 —— 综合性 GC 问题和优化
- Python | Socket01 - 创建一个TCP服务器(阻塞+单线程),将TCP客户端发过来的字符串原路返回
- 160308_Helloworld_Console Application
- php7 ipv6,php将ipv4/ipv6的真实ip转换为数字
- ASP .NET基本概念
- Box2DWeb_03之Shape
- Linux 不同方法查看进程消耗CPU IO 等
- 【渝粤教育】国家开放大学2018年春季 0092-22T民法 参考试题
- 8 种单例模式写法,助你搞定面试!
- ping,python实现批量ping包工具--小案例
- php中smarty模板下载,Smarty模板下载|
- zookeeper-linux集群搭建小结
- qq视频转码失败怎么办_迅捷视频转换器腾讯视频转换失败如何解决?
- 用于单图像超分辨率的增强深度残差网络
- s11 day103 luffy项目结算部分+认证+django-redis
热门文章
- 蔡氏电路matlab仿真实代码验,基于蔡氏电路的MATLAB仿真
- Mybatis辅助神器-MyBatis Log Plugin,定位java中SQL问题
- python文字教学_【纯文本教程】大学专科的Python基础开发课?p=17
- Altium Designer之4层板基本规则设置
- 微信屏蔽网址的解决办法:366API轻松实现被微信屏蔽的网址在微信内正常访问
- GUI提示功控件,LVGL『Label标签控件』介绍
- 北京市海淀区踢球场地指南
- 【Vivado那些事】OOC综合方式
- 看精神小伙是如何智斗骗子的
- 把100PB数据迁移到阿里云,需要几步?