当拖动右下角区域时执行围绕图像中心旋转,缩放的操作,拖动其他区域执行平移。
采用Matrix变换实现,最后可以保存在文件。
效果如下:
View的代码如下:
package com.hu.imagepro; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Matrix; import android.graphics.Paint; import android.graphics.Paint.Style; import android.graphics.PaintFlagsDrawFilter; import android.graphics.PointF; import android.graphics.RectF; import android.os.Environment; import android.view.MotionEvent; import android.view.View; import com.example.imageprocess.R; public class ProcessView extends View{ Context context = null; Matrix matrixPaint = null; Bitmap bmpMotion = null; Bitmap bmpRotate = null; Bitmap bmpBack = null; RectF rectMotionPre = null; RectF rectMotion = null; RectF rectRotateMark = null; RectF rectRotatePre = null; RectF rectRotate = null; Paint paint = null; PaintFlagsDrawFilter paintFilter = null; ViewStatus status = ViewStatus.STATUS_MOVE; PointF pointMotionMid = null; PointF prePoint = null; PointF curPoint = null; PointF rotateCenterP = null; String savePath = null; enum ViewStatus{ STATUS_ROTATE, STATUS_MOVE, } public ProcessView(Context context) { super(context); // TODO Auto-generated constructor stub this.context = context; //创建变幻图形用的Matrix matrixPaint = new Matrix(); //创建画笔 paint = new Paint(); //画笔抗锯齿 paint.setAntiAlias(true); paint.setColor(Color.BLUE); //设置画笔绘制空心图形 paint.setStyle(Style.STROKE); try { //加载相应的图片资源 bmpMotion = BitmapFactory.decodeStream(context.getAssets().open("wenzi_14.png")); bmpBack = BitmapFactory.decodeStream(context.getAssets().open("background.png")); bmpRotate = BitmapFactory.decodeResource(getResources(), R.drawable.btn_rotate_a); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } //记录表情最初的矩形 rectMotionPre = new RectF(0, 0, bmpMotion.getWidth(), bmpMotion.getHeight()); //记录表情当前的矩形 rectMotion = new RectF(rectMotionPre); //标记旋转图标位置的矩形 rectRotateMark = new RectF(rectMotion.right - bmpRotate.getWidth() / 2, rectMotion.bottom - bmpRotate.getHeight() / 2, rectMotion.right + bmpRotate.getWidth() / 2, rectMotion.bottom + bmpRotate.getHeight() / 2); //记录旋转图标矩形最初的矩形 rectRotatePre = new RectF(rectRotateMark); //记录当前旋转图标位置的矩形 rectRotate = new RectF(rectRotateMark); //记录表情矩形的中点 pointMotionMid = new PointF(bmpMotion.getWidth() / 2, bmpMotion.getHeight() / 2); //记录上次动作的坐标 prePoint = new PointF(); //记录当前动作的坐标 curPoint = new PointF(); //记录旋转图标中点 rotateCenterP = new PointF(rectMotion.right, rectMotion.bottom); //画布参数 paintFilter = new PaintFlagsDrawFilter(0, Paint.ANTI_ALIAS_FLAG|Paint.FILTER_BITMAP_FLAG); savePath = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + "test123.png"; } @Override protected void onDraw(Canvas canvas) { // TODO Auto-generated method stub canvas.setDrawFilter(paintFilter); canvas.drawBitmap(bmpBack, 0, 0, paint); canvas.drawBitmap(bmpMotion, matrixPaint, null); canvas.drawBitmap(bmpRotate, null, rectRotate, null); // canvas.drawRect(rectPaint, paint); // canvas.drawRect(rectRotate, paint); // canvas.drawCircle(picMidPoint.x, picMidPoint.y, 5, paint); super.onDraw(canvas); } @Override public boolean onTouchEvent(MotionEvent event) { // TODO Auto-generated method stub float x = event.getX(); float y = event.getY(); switch (event.getAction()) { //手指按下的时候 case MotionEvent.ACTION_DOWN: prePoint.x = x; prePoint.y = y; //按到了旋转图标上 if(isInRect(x, y, rectRotate)){ status = ViewStatus.STATUS_ROTATE; }else{ status = ViewStatus.STATUS_MOVE; } break; case MotionEvent.ACTION_UP: if(status == ViewStatus.STATUS_ROTATE){ saveBitmap(); } break; case MotionEvent.ACTION_MOVE: curPoint.x = x; curPoint.y = y; if(status == ViewStatus.STATUS_ROTATE){ rectRotateMark.set(x - bmpRotate.getWidth() / 2, y - bmpRotate.getHeight() / 2, x + bmpRotate.getWidth() / 2, y + bmpRotate.getHeight() / 2); //获取旋转的角度 float de = getPointsDegree(prePoint, pointMotionMid, curPoint); //获取缩放的比例 float re = getPointsDistance(pointMotionMid, curPoint) / getPointsDistance(pointMotionMid, prePoint); if(re > 0.0001){ //对Matrix进行缩放 matrixPaint.postScale(re, re, pointMotionMid.x, pointMotionMid.y); } if(de > 0.0001 || de < -0.0001){ //对Matrix进行旋转 matrixPaint.postRotate(de, pointMotionMid.x, pointMotionMid.y); } }else if(status == ViewStatus.STATUS_MOVE){ //对Matrix进行移位 matrixPaint.postTranslate(x - prePoint.x, y - prePoint.y); } prePoint.x = x; prePoint.y = y; //将矩阵map到表情矩形上 matrixPaint.mapRect(rectMotion, rectMotionPre); matrixPaint.mapRect(rectRotateMark, rectRotatePre); getRectCenter(rectRotateMark, rotateCenterP); getRectCenter(rectMotion, pointMotionMid); rectRotate.set(rotateCenterP.x - bmpRotate.getWidth() / 2, rotateCenterP.y - bmpRotate.getHeight() / 2, rotateCenterP.x + bmpRotate.getWidth() / 2, rotateCenterP.y + bmpRotate.getHeight() / 2); postInvalidate(); break; default: break; } return true; } /** * 将当前表情合并到背景并保存 */ private void saveBitmap() { File f = new File(savePath); //使用背景图的宽高创建一张bitmap Bitmap bmpSave = Bitmap.createBitmap(bmpBack.getWidth(), bmpBack.getHeight(), Bitmap.Config.ARGB_8888); //创建canvas Canvas canvas = new Canvas(bmpSave); //将背景图和表情画在bitmap上 canvas.drawBitmap(bmpBack, 0, 0, paint); canvas.drawBitmap(bmpMotion, matrixPaint, paint); //保存bitmap // canvas.save(Canvas.ALL_SAVE_FLAG); // canvas.restore(); try{ FileOutputStream out = new FileOutputStream(f); bmpSave.compress(Bitmap.CompressFormat.PNG, 100, out); out.flush(); out.close(); } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } bmpBack.recycle(); bmpBack = bmpSave; //重置Matrix matrixPaint.reset(); //充值旋转图标 rectRotate.set(rectRotatePre); } //根据矩形获取中心点 private void getRectCenter(RectF rect, PointF p){ p.x = rect.left + (rect.right - rect.left) / 2; p.y = rect.top + (rect.bottom - rect.top) / 2; } //判断点是否在矩形内 private boolean isInRect(float x, float y, RectF rect){ boolean ret = false; if(x > rect.left && x < rect.right && y > rect.top && y < rect.bottom){ ret = true; } return ret; } //求两点间距离 private float getPointsDistance(PointF p1, PointF p2) { float ret = (float) Math.sqrt(Math.abs((p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y))); return ret; } //求角ABC private float getPointsDegree(PointF a, PointF b, PointF c){ if(Math.abs(a.x - c.x) < 2 && Math.abs(a.y - c.y) < 2){ return 0.0f; } float ret = (float) ( Math.toDegrees(Math.atan2(c.y - b.y, c.x - b.x) - Math.atan2(a.y - b.y, a.x - b.x))); return ret; } }
完
相关推荐
图片对比工具,挺好玩的
全能魔图是一款专业好用的店铺图片下载软件。软件支持淘宝、天猫、京东、阿里巴巴、国美、苏宁、当当、折800、唯品会等诸多网店,可以实现快速的将店铺首页、描述、主图等图片信息抓取出来,还支持批量操作。软件...
疯狂猜图、百度魔图和魔漫相机为啥能火.docx
ImageFilterForAndroid- 图片处理类似百度魔图里的特效
图片-魔术 使用遗传算法解决魔图问题的进化计算项目 开发商: 德尼尔森 Yesid Basante ----- Juan Manuel Chaguendo
微信小程序 图片添加圣诞帽的源码 无需后端 小程序汇总搜索 魔图变幻
魔图 在此项目中,我们根据以下模型生成数据库。 完全强子顶衰变 : pp > tt~ QED=0, (t > W+ b, W+ > jj), (t~ > w- b~, w- > jj ) 与希克夸克有关的标准希格斯玻色子 : pp > tt~ h , (t > W+ b, W+ > jj), (t~ ...
2020长安杯电子取证复盘.rar
Office_Password_Unlocker_V4.0
FreeUPX 一款优秀的 UPX 外壳,其 1.4 版本支持目前最新的 upx 3.7。 UPX(the Ultimate Packer for eXecutables)是一个... 具有极佳的压缩比,还可以对未压缩的文件和压缩完后进行比较,Free UPX 1.0是它的外壳程序。
1. 理解计算机网络的基本概念。 2. 掌握局域网的基本工作原理。 3. 掌握TCP/ IP及其相关协议。 4. 掌握Internet 基本服务类型。 5. 掌握较为新型的网络技术应用。 6. 理解网络管理与网络安全原理。