Android图片裁剪

给出一张图片,用户手动选择需要的图片区域进行裁剪获得:

自定义一个继承自ImageView可手动选择裁剪区域的控件Crop_Canvas:

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.WindowManager;
import android.widget.ImageView;

import com.hp.classes.wt.R;

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 static final int LEFT_AREA_ALPHA = 50 * 255 / 100; //选择区域外背景
    private int mx = 0; // 触笔点击位置的X坐标
    private int my = 0; // 触笔点击位置的Y坐标
    private int recFlag = -1; // 用来存储触笔点击了哪个小矩形框(改变选择区域大小的小矩形框)
    private int width  = 0;
    private int height = 0;
    
    private Bitmap bitMap = null; // 原始图片
    private boolean touchFlag = false; // 触笔是否在选择框内
    private boolean firstFlag = false;

    private RectF dst = null; // 图片显示区域,也就是drawBitmap函数中的目标dst
    private RectF ChooseArea = null; // 选择区域
    private RectF recLT = null; // 左上角的小矩形框
    private RectF recRT = null; // 右上角的小矩形框
    private RectF recLB = null; // 左下角的小矩形框
    private RectF recRB = null; // 右下角的小矩形框
    private RectF leftRectL = null; //左边阴影矩形
    private RectF leftRectR = null;    //右边阴影矩形
    private RectF leftRectT = null;    //顶部阴影矩形
    private RectF leftRectB = null;    //底部阴影矩形

    private Paint mPaint = 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() {
        WindowManager wm = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);
        this.width = wm.getDefaultDisplay().getWidth() - this.getResources().getDimensionPixelOffset(R.dimen.classes_dp_40);
        this.height = wm.getDefaultDisplay().getHeight();
        
        recLT = new RectF();
        recLB = new RectF();
        recRT = new RectF();
        recRB = new RectF();
        dst = new RectF();
        firstFlag = true;
        
        // 选择框边线画笔
        mPaint = new Paint();
        mPaint.setColor(Color.RED);
        mPaint.setStyle(Paint.Style.STROKE); // 将画笔的风格改为空心
        // 选择框之外的灰色区域画笔,分成四个矩形框
        leftAreaPaint = new Paint();
        leftAreaPaint.setStyle(Paint.Style.FILL);
        leftAreaPaint.setAlpha(Crop_Canvas.LEFT_AREA_ALPHA);
    }

    public void setBitmap(Bitmap bitmap) {
        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() {
        dst.set(dst.left, dst.top, this.width, this.height);
        int centerX = this.width / 2;
        int centerY = this.height /2;
        ChooseArea = new RectF();
        ChooseArea.set(centerX - 300, centerY - 150, centerX + 300, centerY + 150);
        this.set_LeftArea_Alpha();
        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);
        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 ) {

            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) {
            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如下:

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

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

import com.hp.classes.config.Constants;
import com.hp.classes.tools.CommonUtils;
import com.hp.classes.tools.ImageCache;
import com.hp.classes.ui.BaseActivity;
import com.hp.classes.ui.newui.view.Crop_Canvas;
import com.hp.classes.wt.R;
import com.hp.open.tools.StringUtils;

public class PictrueEditAcitivty extends BaseActivity implements OnClickListener {
    private Button btnBack, btnCompleted, btnRotate90;
    private String path;
    private Crop_Canvas canvas;
    private Bitmap backgroudBitmap;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.classes_activity_picture_editing_new);
        path = getIntent().getExtras().getString(Constants.WRONG_TITLE_PATH);
        if (!StringUtils.isValid(path)) {
            return;
        }
        initView();
    }

    private void initView() {
        btnBack = (Button) findViewById(R.id.btnBack);
        btnBack.setOnClickListener(this);
        btnCompleted = (Button) findViewById(R.id.btnCompleted);
        btnCompleted.setOnClickListener(this);
        btnRotate90 = (Button) findViewById(R.id.btnRotate90);
        btnRotate90.setOnClickListener(this);
        canvas = (Crop_Canvas) findViewById(R.id.myCanvas);
        init();
    }

    private void init() {
        try {//对图片实现大小压缩
            int screenWidth = getResources().getDisplayMetrics().widthPixels;
            int screenHeight = getResources().getDisplayMetrics().heightPixels;
            Constants.CACHEIMAGE_SIZE = screenWidth * screenHeight;

            BitmapFactory.Options opt = new BitmapFactory.Options();
            opt.inSampleSize = 1;
            opt.inJustDecodeBounds = true;// 为true时,只返回宽高,不返回bitmap
            BitmapFactory.decodeFile(path, opt);
            int bitmapSize = opt.outHeight * opt.outWidth;
            if (bitmapSize > Constants.CACHEIMAGE_SIZE && Constants.CACHEIMAGE_SIZE != 0) {
                opt.inSampleSize = bitmapSize / Constants.CACHEIMAGE_SIZE;
            }
            opt.inJustDecodeBounds = false;
            backgroudBitmap = BitmapFactory.decodeFile(path, opt);
            canvas.setBitmap(backgroudBitmap);
        } catch (Exception e) {
            e.printStackTrace();
            e.printStackTrace();
            ImageCache.getInstance(this).clearCache();
            backgroudBitmap = BitmapFactory.decodeFile(path);
            canvas.setBitmap(backgroudBitmap);
        }
        if (backgroudBitmap == null) {
            finish();
        }
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
        case R.id.btnBack:
            // 删除图片
            CommonUtils.startTakePhotoActivity(this);
            break;
        case R.id.btnCompleted:
            saveTitlePictrue();
            break;
        case R.id.btnRotate90:
            long temp = System.currentTimeMillis();
                backgroudRotate90();
            break;
        default:
            break;
        }
    }

    public void saveTitlePictrue() {
        // 图片保存的路径,之后将之转换为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();
        }
        finish();
    }

    private void backgroudRotate90() {
        Matrix m = new Matrix();
        m.setRotate(90, (float) backgroudBitmap.getWidth() / 2, (float) backgroudBitmap.getHeight() / 2);
        float targetX, targetY;
        targetX = backgroudBitmap.getHeight();
        targetY = 0;

        final float[] values = new float[9];
        m.getValues(values);

        float x1 = values[Matrix.MTRANS_X];
        float y1 = values[Matrix.MTRANS_Y];

        m.postTranslate(targetX - x1, targetY - y1);

        Bitmap bm1 = Bitmap.createBitmap(backgroudBitmap.getHeight(), backgroudBitmap.getWidth(), Bitmap.Config.ARGB_8888);

        Paint paint = new Paint();
        Canvas cv = new Canvas(bm1);
        cv.drawBitmap(backgroudBitmap, m, paint);
        backgroudBitmap = bm1;
        canvas.setBitmap(backgroudBitmap);
    }
}

classes_activity_picture_editing_new.xml布局如下:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/llRoot"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/mask" >

    <LinearLayout
        android:id="@+id/llRight"
        android:layout_width="@dimen/classes_dp_40"
        android:layout_height="match_parent"
        android:layout_alignParentRight="true"
        android:background="#2b2b2b"
        android:gravity="center_horizontal"
        android:orientation="vertical" >

        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="0dip"
            android:layout_weight="1"
            android:gravity="center" >

            <Button
                android:id="@+id/btnBack"
                style="@style/PETextButton"
                android:background="@drawable/classes_pe_button_back" />
        </LinearLayout>

        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="0dip"
            android:layout_weight="1"
            android:gravity="center" >

            <Button
                android:id="@+id/btnCompleted"
                style="@style/PETextButton"
                android:background="@drawable/classes_pe_button_completed" />
        </LinearLayout>

        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="0dip"
            android:layout_weight="1"
            android:gravity="center" >

            <Button
                android:id="@+id/btnRotate90"
                style="@style/PETextButton"
                android:background="@drawable/classes_pe_button_rotate90" />
        </LinearLayout>
    </LinearLayout>

     <com.hp.classes.ui.newui.view.Crop_Canvas
        android:id="@+id/myCanvas"
        android:layout_width="fill_parent"
        android:layout_height="match_parent"
        android:layout_toLeftOf="@+id/llRight"
        android:scaleType="fitXY"
        android:background="@color/black" />

</RelativeLayout>



  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值