软件编程
位置:首页>> 软件编程>> Android编程>> Android实现图片的裁剪(不调用系统功能)

Android实现图片的裁剪(不调用系统功能)

作者:LCore  发布时间:2021-05-25 23:26:41 

标签:Android,图片裁剪

接上一篇文章:Android实现图片区域裁剪功能

上一篇文章提及了通过调用系统相册或拍照来实现图片的缩放\裁剪。不过这对于笔者项目的要求同样不适合,笔者需要的是通过对手机屏幕整个进行一个截图,并对这个截图进行裁剪操作。

依靠系统功能确实可以实现图片的裁剪,但是不够灵活。这里笔者提供一种较为灵活的做法。

但是这种做法的用户体验没有上篇文章的好,至于使用何种方法,读者应该自己衡量。

同样,我们先看实际效果图。

这里展示的是笔者项目的一小部分(阅读器):

Android实现图片的裁剪(不调用系统功能)

我们点击左下角的剪切按钮

Android实现图片的裁剪(不调用系统功能)

我们通过红色边框的四个角来控制裁剪的大小,移动红色框体来控制裁剪的位置区域。

接下来我们看看源码的实现:

首先点击剪切按钮的时候,我们应该生成一个Bitmap对象,传递给另一个Activty处理 

具体做法如下:


cutP.setOnClickListener(new View.OnClickListener() {

public void onClick(View v) {
   //将一些按钮隐藏
   cutP.setVisibility(View.INVISIBLE);
   mTopBarSwitcher.setVisibility(View.INVISIBLE);
   mPageSlider.setVisibility(View.INVISIBLE);
   back.setVisibility(View.INVISIBLE);
   mPageNumberView.setVisibility(View.INVISIBLE);
   View view = MuPDFActivity.this.getWindow().getDecorView();
   if (false == view.isDrawingCacheEnabled()) {
    view.setDrawingCacheEnabled(true);
   }
   Bitmap bitmap = view.getDrawingCache();
   ImageView imgv = new ImageView(MuPDFActivity.this);
   imgv.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT,
     LayoutParams.FILL_PARENT-200));
   imgv.setImageBitmap(bitmap);
   backBitmap = bitmap;
   //传递给另一个Activity进行裁剪
   Intent intent = new Intent();
   intent.setClass(MuPDFActivity.this, CutActivity.class);
   startActivity(intent);

}

});

Tips:这里笔者是将这个截取的Bitmap对象传递给另一个Actvity做相关处理,这里如何在Activity之间进行Bitmap传递呢?这里我们简单的运用java语法特性来完成具体做法如下:

我们在ActvityA中有一个public static Bitmap bitmap对象,当ActivityA跳转到B时,我们直接通过ActivityA.bitmap来获取这个对象。

之后就是如何进行裁剪的操作了。操作在另一个Activity中进行。XML配置文件信息如下: 


<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<com.artifex.mupdf.Crop_Canvas
 android:id="@+id/myCanvas"
 android:layout_width="fill_parent"
 android:layout_height="fill_parent"
 android:background="#313131"
 />
<Button
 android:id="@+id/cutCancel"
 android:layout_height="wrap_content"
 android:layout_width="wrap_content"
 android:text="取消"
 android:layout_alignParentBottom="true"
 android:layout_alignParentLeft="true"/>
<Button
 android:id="@+id/cutEnsure"
 android:layout_height="wrap_content"
 android:layout_width="wrap_content"
 android:text="确定"
 android:layout_alignParentBottom="true"
 android:layout_centerInParent="true"/>
<Button
 android:id="@+id/toPDF"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:text="ToPDF"
 android:layout_alignParentBottom="true"
 android:layout_alignParentRight="true"/>
</RelativeLayout>

通过配置文件可以看到我们自定义了一个View(ImageView)其实现如下:


package com.artifex.mupdf;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Bitmap.Config;
import android.graphics.drawable.BitmapDrawable;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.ImageView;

public class Crop_Canvas extends ImageView {

private final static int PRESS_LB = 0;//表示左下角矩形框
private final static int PRESS_LT = 1;//表示左上角矩形框
private final static int PRESS_RB = 2;//表示右下角矩形框
private final static int PRESS_RT = 3;//表示右上角矩形框

private Bitmap bitMap = null;    //原始图片
private RectF src = null;     //经过比例转换后的裁剪区域
private RectF dst = null;     //图片显示区域,也就是drawBitmap函数中的目标dst
private RectF ChooseArea = null;    //选择区域    
private Paint mPaint = null;    //画笔
private Matrix matrix = null;    //矩阵

private int mx = 0;       //存储触笔移动时,之前�?��的触笔的x坐标
private int my = 0;       //存储触笔移动时,之前�?��的触笔的y坐标
private boolean touchFlag = false;   //触笔是否在屏幕之�?
private boolean cutFlag = false;   //是否点击了menu上的裁剪按钮
private int recFlag = -1;     //用来存储触笔点击了哪个小矩形框(改变选择区域大小的小矩形框)
private boolean firstFlag = false;

private RectF recLT = null;     //左上角的小矩形框
private RectF recRT = null;     //右上角的小矩形框
private RectF recLB = null;     //左下角的小矩形框
private RectF recRB = null;     //右下角的小矩形框
private static final int LEFT_AREA_ALPHA = 50 * 255 / 100;
private RectF leftRectL = null;
private RectF leftRectR = null;
private RectF leftRectT = null;
private RectF leftRectB = null;
private Paint leftAreaPaint = null;

public Crop_Canvas(Context context, AttributeSet attrs) {
 super(context, attrs);
 this.init();
}

public Crop_Canvas(Context context) {
 super(context);
 this.init();
}

public void init(){
 cutFlag = true;
 recLT = new RectF();
 recLB = new RectF();
 recRT = new RectF();
 recRB = new RectF();
 dst = new RectF();
 mPaint = new Paint();
 mPaint.setColor(Color.RED);
 mPaint.setStyle(Paint.Style.STROKE);  //将画笔的风格改为空心
 ChooseArea = new RectF();
 this.setPressRecLoc();
 src = null;
 firstFlag = true;

//选择框之外的灰色区域,分成四个矩形框

leftAreaPaint = new Paint();
 leftAreaPaint.setStyle(Paint.Style.FILL);
 leftAreaPaint.setAlpha(Crop_Canvas.LEFT_AREA_ALPHA);
}

public void setBitmap(Bitmap bitmap){
 BitmapDrawable bd = new BitmapDrawable(bitmap);
 src = new RectF(0,0,bd.getIntrinsicWidth(),bd.getIntrinsicHeight());
 this.bitMap = bitmap.copy(Config.ARGB_8888, true);

this.setImageBitmap(bitMap);
 leftRectB = new RectF();
 leftRectL = new RectF();
 leftRectR = new RectF();
 leftRectT = new RectF();
}

public void imageScale(){
 matrix = this.getImageMatrix();
 matrix.mapRect(dst, src);
 int padding = this.getPaddingBottom();
 int width = bitMap.getWidth();
 int height = bitMap.getHeight();
 //dst.set(dst.left+padding,dst.top+padding,dst.right+padding,dst.bottom+padding);
 dst.set(dst.left+20,dst.top+20,width-20,height - 40);
 ChooseArea = new RectF(dst);
 this.setPressRecLoc();
}

public Bitmap getSubsetBitmap(){
 float ratioWidth = bitMap.getWidth()/(float)(dst.right-dst.left);
 float ratioHeight = bitMap.getHeight()/(float)(dst.bottom - dst.top);
 int left = (int)((ChooseArea.left - dst.left) * ratioWidth);
 int right = (int)(left + (ChooseArea.right - ChooseArea.left) * ratioWidth);
 int top = (int)((ChooseArea.top - dst.top) * ratioHeight);
 int bottom = (int)(top + (ChooseArea.bottom - ChooseArea.top) * ratioHeight);
 src = new RectF(left,top,right,bottom);
 firstFlag = true;
 set_LeftArea_Alpha();
 return Bitmap.createBitmap(bitMap, left, top, right-left, bottom-top);
}

//获得ChooseArea对象
public RectF getChooseArea(){
 return ChooseArea;
}

public void moveChooseArea(int move_x,int move_y){
 if(ChooseArea.left + move_x >= dst.left && ChooseArea.right + move_x <= dst.right
 && ChooseArea.top + move_y >= dst.top && ChooseArea.bottom + move_y <= dst.bottom){
  ChooseArea.set(ChooseArea.left + move_x,ChooseArea.top+move_y
    ,ChooseArea.right + move_x,ChooseArea.bottom+move_y);
 }else{
  if(ChooseArea.left + move_x < dst.left){
   ChooseArea.set(dst.left,ChooseArea.top
     ,ChooseArea.right+dst.left-ChooseArea.left,ChooseArea.bottom);
  }
  if(ChooseArea.right + move_x > dst.right){
   ChooseArea.set(ChooseArea.left+dst.right-ChooseArea.right,ChooseArea.top
     ,dst.right,ChooseArea.bottom);
  }

if(ChooseArea.top + move_y < dst.top){
   ChooseArea.set(ChooseArea.left,dst.top
     ,ChooseArea.right,ChooseArea.bottom+dst.top-ChooseArea.top);
  }

if(ChooseArea.bottom + move_y > dst.bottom){
   ChooseArea.set(ChooseArea.left,ChooseArea.top+dst.bottom-ChooseArea.bottom
     ,ChooseArea.right,dst.bottom);
  }
 }
 this.setPressRecLoc();
 mPaint.setColor(Color.GREEN);
 this.invalidate();
}

public boolean onTouchEvent(MotionEvent event){
 mPaint.setColor(Color.RED);

if(event.getAction() == MotionEvent.ACTION_DOWN && cutFlag){
  //System.out.println(event.getX() + "," + event.getY());

mx = (int)event.getX();
  my = (int)event.getY();
  if(this.judgeLocation(mx,my)){
   touchFlag = true;
   mPaint.setColor(Color.GREEN);
   this.invalidate();
   return true;
  }else{

if(this.findPresseddst((int)event.getX(), (int)event.getY())){
    touchFlag = true;
    mPaint.setColor(Color.RED);
    return true;
   }
  }
 }

if(event.getAction() == MotionEvent.ACTION_MOVE && touchFlag){
  //判断是否点击了哪个个小矩形框
  if(this.isOutOfArea((int)event.getX(), (int)event.getY())){
   return true;
  }

//如果选择区域大小跟图像大小一样时,就不能移动
  if(ChooseArea.left == dst.left && ChooseArea.top == dst.top &&
   ChooseArea.right == dst.right && ChooseArea.bottom == dst.bottom){
  }else{
   this.moveChooseArea((int)event.getX() - mx, (int)event.getY() - my);
   mx = (int)event.getX();
   my = (int)event.getY();
  }
 }

if(event.getAction() == MotionEvent.ACTION_UP){
  recFlag = -1;
  this.invalidate();
  touchFlag = false;
 }

return super.onTouchEvent(event);
}

private boolean isOutOfArea(int x,int y){
 switch(recFlag){
 case Crop_Canvas.PRESS_LB:
  this.pressLB(x - mx, y - my);
  break;
 case Crop_Canvas.PRESS_LT:
  this.pressLT(x - mx, y - my);
  break;
 case Crop_Canvas.PRESS_RB:
  this.pressRB(x - mx, y - my);
  break;
 case Crop_Canvas.PRESS_RT:
  this.pressRT(x - mx, y - my);
  break;
 default:return false;
 }
 mx = x;
 my = y;
 this.invalidate();
 return true;
}

public boolean findPresseddst(int x,int y){
 boolean returnFlag = false;
 if(this.isInRect(x, y, recLB)){
  recFlag = Crop_Canvas.PRESS_LB;
  returnFlag = true;
 }else if(this.isInRect(x, y, recLT)){
  recFlag = Crop_Canvas.PRESS_LT;
  returnFlag = true;
 }else if(this.isInRect(x, y, recRB)){
  recFlag = Crop_Canvas.PRESS_RB;
  returnFlag = true;
 }else if(this.isInRect(x, y, recRT)){
  recFlag = Crop_Canvas.PRESS_RT;
  returnFlag = true;
 }

return returnFlag;
}

public boolean isInRect(int x,int y,RectF rect){
 if(x >= rect.left -20 && x <= rect.right + 20 && y > rect.top - 20 && y < rect.bottom + 20){
  return true;
 }
 return false;
}

private void pressLB(int x,int y){
 float left = ChooseArea.left + x;
 float right = ChooseArea.right;
 float top = ChooseArea.top;
 float bottom = ChooseArea.bottom + y;
 if(left <= right - 30 && left >= dst.left && bottom <= dst.bottom && bottom >= top + 30){
   ChooseArea.set(left,top,right,bottom);
 }else{
  if(left + x < dst.left){
   left = dst.left;
  }

if(bottom + y > dst.bottom){
   bottom = dst.bottom;
  }

if(ChooseArea.left + x > ChooseArea.right - 30){
   left = ChooseArea.right - 30;
  }

if(ChooseArea.bottom + y < ChooseArea.top + 30){
   bottom = ChooseArea.top + 30;
  }
  ChooseArea.set(left,top,right,bottom);
 }
 this.setPressRecLoc();
}

private void pressLT(int x,int y){
 float left = ChooseArea.left + x;
 float right = ChooseArea.right;
 float top = ChooseArea.top + y;
 float bottom = ChooseArea.bottom;
 if(left <= right - 30 && left >= dst.left && top <= bottom - 30 && top >= dst.top){
  ChooseArea.set(left,top,right,bottom);
 }else{
  if(left < dst.left){
   left = dst.left;
  }

if(top < dst.top){
   top = dst.top;
  }

if(left > right - 30){
   left = right - 30;
  }

if(top > bottom - 30){
   top = bottom - 30;
  }
  ChooseArea.set(left,top,right,bottom);
 }
 this.setPressRecLoc();
}

private void pressRT(int x,int y){
 float left = ChooseArea.left;
 float right = ChooseArea.right + x;
 float top = ChooseArea.top + y;
 float bottom = ChooseArea.bottom;

if(right <= dst.right && right >= left + 30 && top <= bottom - 30 && top >= dst.top){
  ChooseArea.set(left,top,right,bottom);
 }else{
  if(right > dst.right){
   right = dst.right;
  }

if(top < dst.top){
   top = dst.top;
  }

if(right < left + 30){
   right = left + 30;
  }

if(top > bottom - 30){
   top = bottom - 30;
  }
  ChooseArea.set(left,top,right,bottom);
 }
 this.setPressRecLoc();
}

private void pressRB(int x,int y){
 float left = ChooseArea.left;
 float right = ChooseArea.right + x;
 float top = ChooseArea.top;
 float bottom = ChooseArea.bottom + y;

if(right<= dst.right && right >= left + 30 && bottom <= dst.bottom && bottom >= top + 30){
  ChooseArea.set(left,top,right,bottom);
 }else{
  if(right > dst.right){
   right = dst.right;
  }

if(bottom > dst.bottom){
   bottom = dst.bottom;
  }

if(right < left + 30){
   right = left + 30;
  }

if(bottom < top + 30){
   bottom = top + 30;
  }
  ChooseArea.set(left,top,right,bottom);
 }
 this.setPressRecLoc();
}

//每次改变选择区域矩形的大小或者移动,各角落上的小矩形也要改变它的Location
private void setPressRecLoc(){
 recLT.set(ChooseArea.left-5,ChooseArea.top-5 , ChooseArea.left+5, ChooseArea.top+5);
 recLB.set(ChooseArea.left-5,ChooseArea.bottom-5 , ChooseArea.left+5, ChooseArea.bottom+5);
 recRT.set(ChooseArea.right-5,ChooseArea.top-5 , ChooseArea.right+5, ChooseArea.top+5);
 recRB.set(ChooseArea.right-5,ChooseArea.bottom-5 , ChooseArea.right+5, ChooseArea.bottom+5);
}

public boolean judgeLocation(float x,float y){
 float start_x = this.getChooseArea().left;
 float start_y = this.getChooseArea().top;
 float last_x = this.getChooseArea().right;
 float last_y = this.getChooseArea().bottom;
 //System.out.println("chubi:" + x + "," + y);
 //System.out.println(start_y + "," + last_y);
 if(x > start_x+10 && x < last_x-10 && y > start_y+10 && y < last_y-10){
  return true;
 }
 return false;
}

public void onDraw(Canvas canvas){
 super.onDraw(canvas);
 if(firstFlag){
  this.imageScale();
  firstFlag = false;
  mPaint.setColor(Color.RED);
  System.out.println("Width: " + (dst.right - dst.left));
  System.out.println("Height: " + (dst.bottom - dst.top));
  System.out.println("Width: " + this.getDrawable().getIntrinsicWidth());
  System.out.println("Height: " + this.getDrawable().getIntrinsicHeight());
 }else{
  set_LeftArea_Alpha();
 }
 canvas.drawRect(ChooseArea, mPaint);
 mPaint.setColor(Color.BLUE);
 canvas.drawRect(recLT, mPaint);
 canvas.drawRect(recLB, mPaint);
 canvas.drawRect(recRT, mPaint);  
 canvas.drawRect(recRB, mPaint);

canvas.drawRect(leftRectL, leftAreaPaint);
 canvas.drawRect(leftRectR, leftAreaPaint);
 canvas.drawRect(leftRectT, leftAreaPaint);
 canvas.drawRect(leftRectB, leftAreaPaint);

}

public void set_LeftArea_Alpha(){
 leftRectL.set(dst.left, dst.top, ChooseArea.left, dst.bottom);
 leftRectR.set(ChooseArea.right,dst.top,dst.right,dst.bottom);
 leftRectT.set(ChooseArea.left, dst.top, ChooseArea.right, ChooseArea.top);
 leftRectB.set(ChooseArea.left,ChooseArea.bottom,ChooseArea.right,dst.bottom);
}
}

接下来直接看看Activity源码:


package com.artifex.mupdf.cut;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;

import android.app.Activity;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.Window;
import android.widget.Button;

import com.andorid.shu.love.R;
import com.artifex.mupdf.Crop_Canvas;
import com.artifex.mupdf.MuPDFActivity;

public class CutActivity extends Activity {
private Crop_Canvas canvas = null;
private Bitmap backBitmap;
private Button cancel;
private Button ensure;
private Button toPDF;

@Override
protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 requestWindowFeature(Window.FEATURE_NO_TITLE);
 setContentView(R.layout.cut_image);
 backBitmap = MuPDFActivity.backBitmap;
 init();
 cancel = (Button) findViewById(R.id.cutCancel);
 cancel.setOnClickListener(new OnClickListener() {

@Override
  public void onClick(View v) {
   CutActivity.this.finish();
  }
 });
 ensure = (Button) findViewById(R.id.cutEnsure);
 ensure.setOnClickListener(new OnClickListener() {
  @Override
  public void onClick(View v) {
   //图片保存的路径,之后将之转换为PDF,并以附件的形似发送邮件
   File tmp = new File("/sdcard/lovereader/pic");
   tmp.mkdirs();
   File f = new File("/sdcard/lovereader/pic/" + "testpic" + ".png");
   try {
    f.createNewFile();
   } catch (IOException e1) {
    // TODO Auto-generated catch block
    e1.printStackTrace();
   }
   FileOutputStream fOut = null;
   try {
     fOut = new FileOutputStream(f);
   } catch (FileNotFoundException e) {
     e.printStackTrace();
   }
   canvas.getSubsetBitmap().compress(Bitmap.CompressFormat.PNG, 100, fOut);
   try {
     fOut.flush();
   } catch (IOException e) {
     e.printStackTrace();
   }
   try {
     fOut.close();
   } catch (IOException e) {
     e.printStackTrace();
   }
  }
 });

toPDF = (Button)findViewById(R.id.toPDF);
 toPDF.setOnClickListener(new OnClickListener() {

@Override
  public void onClick(View v) {
   // TODO Auto-generated method stub
   ArrayList<String> imageUrllist = new ArrayList<String>();
   imageUrllist.add("/sdcard/lovereader/pic/" + "testpic" + ".png");
   String pdfUrl = "/sdcard/lovereader/tmp/Foreverlove.pdf";
   File tmp = new File("/sdcard/lovereader/tmp");
   tmp.mkdirs();
   File file = PdfManager.Pdf(imageUrllist, pdfUrl);
   try {
    file.createNewFile();
   } catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
   }

}
 });
}

private void init() {
 canvas = (Crop_Canvas) findViewById(R.id.myCanvas);
 Bitmap bitmap = backBitmap;
 canvas.setBitmap(bitmap);
}

}

ok,不依靠系统的简单裁剪功能就实现了,这里笔者就不给出源代码下载了,上述代码读者只要自己改改就可以用了。

来源:http://blog.csdn.net/lcore/article/details/8927748

0
投稿

猜你喜欢

手机版 软件编程 asp之家 www.aspxhome.com