1.openCv配置
从https://github.com/opencv/opencv/releases/tag/3.3.0下载对应的android版本
a. import module 选择
b.还要配置so文件来调取opencv的接口,在main文件夹下创建jniLibs文件夹,如下图:
把下载的native目录下libs文件下的所有文件拷入jniLibs文件下
c.别忘了把module里的build.gradle修改成和你一样的gradle配置
d.配置manifiest
在application标签前添加
在application标签后添加
e.在Activity中实现opencv的初始化
private BaseLoaderCallback mLoaderCallback = new BaseLoaderCallback(this) {
@Override
public void onManagerConnected(int status) {
switch (status) {
case LoaderCallbackInterface.SUCCESS:
{
Log.i(TAG, "OpenCV loaded successfully");
} break;
default:
{
super.onManagerConnected(status);
} break;
}
}
};
@Override
public void onResume()
{
super.onResume();
if (!OpenCVLoader.initDebug()) {
Log.d("OpenCV", "Internal OpenCV library not found. Using OpenCV Manager for initialization");
OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_3_0_0, this, mLoaderCallback);
} else {
Log.d("OpenCV", "OpenCV library found inside package. Using it!");
mLoaderCallback.onManagerConnected(LoaderCallbackInterface.SUCCESS);
}
}
到此为此,opencv配置完成,进入正题,首先先看下效果:
其实实现抠图的效果也就是调用opencv提供的grabcut函数,函数方法如下:
private Bitmap cupBitmap(Bitmap bitmap,int x,int y,int width,int height){
Mat img = new Mat();
//缩小图片尺寸
// Bitmap bm = Bitmap.createScaledBitmap(bitmap,bitmap.getWidth(),bitmap.getHeight(),true);
//bitmap->mat
Utils.bitmapToMat(bitmap, img);
//转成CV_8UC3格式
Imgproc.cvtColor(img, img, Imgproc.COLOR_RGBA2RGB);
//设置抠图范围的左上角和右下角
Rect rect = new Rect(x,y,width,height);
//生成遮板
Mat firstMask = new Mat();
Mat bgModel = new Mat();
Mat fgModel = new Mat();
Mat source = new Mat(1, 1, CvType.CV_8U, new Scalar(Imgproc.GC_PR_FGD));
//这是实现抠图的重点,难点在于rect的区域,为了选取抠图区域,我借鉴了某大神的自定义裁剪View,返回坐标和宽高
Imgproc.grabCut(img, firstMask, rect, bgModel, fgModel,5, Imgproc.GC_INIT_WITH_RECT);
Core.compare(firstMask, source, firstMask, Core.CMP_EQ);
//抠图
Mat foreground = new Mat(img.size(), CvType.CV_8UC3, new Scalar(255, 255, 255));
img.copyTo(foreground, firstMask);
//mat->bitmap
Bitmap bitmap1 = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888);
Utils.matToBitmap(foreground,bitmap1);
return bitmap1;
}
废话不多说,奉上干粮:
import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.RectF;
import android.graphics.drawable.BitmapDrawable;
import android.net.Uri;;
import android.os.Environment;
import android.provider.MediaStore;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.Toast;
import org.opencv.android.BaseLoaderCallback;
import org.opencv.android.LoaderCallbackInterface;
import org.opencv.android.OpenCVLoader;
import org.opencv.android.Utils;
import org.opencv.core.Core;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.opencv.core.Rect;
import org.opencv.core.Scalar;
import org.opencv.imgproc.Imgproc;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
static final int REQUEST_OPEN_IMAGE = 1;
private static final String TAG ="xxx";
MyCropView cropView;
String mCurrentPhotoPath;
boolean targetChose = false;
ProgressDialog dlg;
private Button select;
private Button cut;
private Button modify;
private Button saveImage;
private Bitmap originalBitmap;
private ImageView choiceView;
private boolean hasCut =false;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
cropView = (MyCropView) findViewById(R.id.myCropView);
select = (Button) findViewById(R.id.btn_gray_process);
cut = (Button) findViewById(R.id.btn_cut_process);
modify = (Button) findViewById(R.id.btn_modify_process);
saveImage = (Button) findViewById(R.id.btn_save_process);
choiceView = (ImageView) findViewById(R.id.croppedImageView);
select.setOnClickListener(this);
cut.setOnClickListener(this);
saveImage.setOnClickListener(this);
modify.setOnClickListener(this);
dlg = new ProgressDialog(this);
}
private BaseLoaderCallback mLoaderCallback = new BaseLoaderCallback(this) {
@Override
public void onManagerConnected(int status) {
switch (status) {
case LoaderCallbackInterface.SUCCESS:
{
Log.i(TAG, "OpenCV loaded successfully");
} break;
default:
{
super.onManagerConnected(status);
} break;
}
}
};
@Override
public void onResume()
{
super.onResume();
if (!OpenCVLoader.initDebug()) {
Log.d("OpenCV", "Internal OpenCV library not found. Using OpenCV Manager for initialization");
OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_3_0_0, this, mLoaderCallback);
} else {
Log.d("OpenCV", "OpenCV library found inside package. Using it!");
mLoaderCallback.onManagerConnected(LoaderCallbackInterface.SUCCESS);
}
}
//从图库中选择图片
public void setPic(){
originalBitmap = BitmapFactory.decodeFile(mCurrentPhotoPath);
cropView.setBmpPath(mCurrentPhotoPath);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case REQUEST_OPEN_IMAGE:
if (resultCode == RESULT_OK) {
Uri imgUri = data.getData();
String[] filePathColumn = { MediaStore.Images.Media.DATA };
Cursor cursor = getContentResolver().query(imgUri, filePathColumn,
null, null, null);
cursor.moveToFirst();
int colIndex = cursor.getColumnIndex(filePathColumn[0]);
mCurrentPhotoPath = cursor.getString(colIndex);
cursor.close();
setPic();
}
break;
}
}
//选择剪切区域
private void selectImageCut(){
targetChose = true;
try{
Bitmap cropBitmap = cropView.getCroppedImage();
choiceView.setImageBitmap(cropBitmap);
}catch (Exception e){
e.printStackTrace();
}
}
@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.btn_gray_process:
Intent getPictureIntent = new Intent(Intent.ACTION_GET_CONTENT);
getPictureIntent.setType("image/*");
Intent pickPictureIntent = new Intent(Intent.ACTION_PICK,
MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
Intent chooserIntent = Intent.createChooser(getPictureIntent, "Select Image");
chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, new Intent[] {
pickPictureIntent
});
startActivityForResult(chooserIntent, REQUEST_OPEN_IMAGE);
break;
case R.id.btn_cut_process:
//抠图是耗时的过程,子线程中运行,并dialog提示
if (targetChose){
dlg.show();
dlg.setMessage("正在抠图...");
final RectF croppedBitmapData = cropView.getCroppedBitmapData();
final int croppedBitmapWidth = cropView.getCroppedBitmapWidth();
final int croppedBitmapHeight = cropView.getCroppedBitmapHeight();
new Thread(new Runnable() {
@Override
public void run() {
final Bitmap bitmap = cupBitmap(originalBitmap, (int) croppedBitmapData.left, (int) croppedBitmapData.top, croppedBitmapWidth, croppedBitmapHeight);
runOnUiThread(new Runnable() {
@Override
public void run() {
dlg.dismiss();
hasCut = true;
choiceView.setImageBitmap(bitmap);
}
});
}
}).start();
}
break;
case R.id.btn_modify_process:
selectImageCut();
break;
case R.id.btn_save_process:
if (hasCut){
String s = saveImageToGalleryString(this, ((BitmapDrawable) (choiceView).getDrawable()).getBitmap());
Toast.makeText(this, "保存在"+s, Toast.LENGTH_SHORT).show();
}else {
Toast.makeText(this, "请先扣图", Toast.LENGTH_SHORT).show();
}
break;
}
}
private Bitmap cupBitmap(Bitmap bitmap,int x,int y,int width,int height){
Mat img = new Mat();
//缩小图片尺寸
// Bitmap bm = Bitmap.createScaledBitmap(bitmap,bitmap.getWidth(),bitmap.getHeight(),true);
//bitmap->mat
Utils.bitmapToMat(bitmap, img);
//转成CV_8UC3格式
Imgproc.cvtColor(img, img, Imgproc.COLOR_RGBA2RGB);
//设置抠图范围的左上角和右下角
Rect rect = new Rect(x,y,width,height);
//生成遮板
Mat firstMask = new Mat();
Mat bgModel = new Mat();
Mat fgModel = new Mat();
Mat source = new Mat(1, 1, CvType.CV_8U, new Scalar(Imgproc.GC_PR_FGD));
Imgproc.grabCut(img, firstMask, rect, bgModel, fgModel,5, Imgproc.GC_INIT_WITH_RECT);
Core.compare(firstMask, source, firstMask, Core.CMP_EQ);
//抠图
Mat foreground = new Mat(img.size(), CvType.CV_8UC3, new Scalar(255, 255, 255));
img.copyTo(foreground, firstMask);
//mat->bitmap
Bitmap bitmap1 = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888);
Utils.matToBitmap(foreground,bitmap1);
return bitmap1;
}
@Override
protected void onDestroy() {
super.onDestroy();
if (dlg != null) {
dlg.dismiss();
}
}
//保存在系统图库
public static String saveImageToGalleryString(Context context, Bitmap bmp) {
// 首先保存图片
String storePath = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + "dearxy";
File appDir = new File(storePath);
if (!appDir.exists()) {
appDir.mkdir();
}
String fileName = System.currentTimeMillis() + ".png";
File file = new File(appDir, fileName);
try {
FileOutputStream fos = new FileOutputStream(file);
//通过io流的方式来压缩保存图片
bmp.compress(Bitmap.CompressFormat.PNG, 100, fos);
fos.flush();
fos.close();
//把文件插入到系统图库
//MediaStore.Images.Media.insertImage(context.getContentResolver(), file.getAbsolutePath(), fileName, null);
//保存图片后发送广播通知更新数据库
Uri uri = Uri.fromFile(file);
context.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, uri));
return file.getPath();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
3.自定义的裁剪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.Paint.Style;
import android.graphics.PointF;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Toast;
public class MyCropView extends View {
// Private Constants ///////////////////////////////////////////////////////
private static final float BMP_LEFT = 0f;
private static final float BMP_TOP = 20f;
private static final float DEFAULT_BORDER_RECT_WIDTH = 200f;
private static final float DEFAULT_BORDER_RECT_HEIGHT = 200f;
private static final int POS_TOP_LEFT = 0;
private static final int POS_TOP_RIGHT = 1;
private static final int POS_BOTTOM_LEFT = 2;
private static final int POS_BOTTOM_RIGHT = 3;
private static final int POS_TOP = 4;
private static final int POS_BOTTOM = 5;
private static final int POS_LEFT = 6;
private static final int POS_RIGHT = 7;
private static final int POS_CENTER = 8;
// this constant would be best to use event number
private static final float BORDER_LINE_WIDTH = 6f;
private static final float BORDER_CORNER_LENGTH = 30f;
private static final float TOUCH_FIELD = 10f;
// Member Variables ////////////////////////////////////////////////////////
private String mBmpPath;
private Bitmap mBmpToCrop;
private RectF mBmpBound;
private Paint mBmpPaint;
private Paint mBorderPaint;// 裁剪区边框
private Paint mGuidelinePaint;
private Paint mCornerPaint;
private Paint mBgPaint;
private RectF mDefaultBorderBound;
private RectF mBorderBound;
private PointF mLastPoint = new PointF();
private float mBorderWidth;
private float mBorderHeight;
private int touchPos;
// Constructors ////////////////////////////////////////////////////////////
public MyCropView(Context context) {
super(context);
// TODO Auto-generated constructor stub
init(context);
}
public MyCropView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
// View Methods ////////////////////////////////////////////////////////////
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
// TODO Auto-generated method stub
// super.onSizeChanged(w, h, oldw, oldh);
}
@Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
// super.onDraw(canvas);
if (mBmpPath != null) {
canvas.drawBitmap(mBmpToCrop, null, mBmpBound, mBmpPaint);
canvas.drawRect(mBorderBound.left, mBorderBound.top, mBorderBound.right, mBorderBound.bottom, mBorderPaint);
drawGuidlines(canvas);
drawBackground(canvas);
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
// TODO Auto-generated method stub
// super.onTouchEvent(event);
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
setLastPosition(event);
getParent().requestDisallowInterceptTouchEvent(true);
// onActionDown(event.getX(), event.getY());
touchPos = detectTouchPosition(event.getX(), event.getY());
break;
case MotionEvent.ACTION_MOVE:
onActionMove(event.getX(), event.getY());
setLastPosition(event);
break;
case MotionEvent.ACTION_UP:
break;
}
return true;
}
// Public Methods //////////////////////////////////////////////////////////
public String getBmpPath() {
return mBmpPath;
}
public void setBmpPath(String picPath) {
this.mBmpPath = picPath;
setBmp();
}
public RectF getCroppedBitmapData(){
return mBorderBound;
}
public int getCroppedBitmapWidth(){
return (int) mBorderWidth;
}
public int getCroppedBitmapHeight(){
return (int) mBorderHeight;
}
public Bitmap getCroppedImage() {
// 先不考虑图片被压缩的情况 就当作现在的图片就是1:1的
Bitmap bitmap = null;
try {
bitmap = Bitmap.createBitmap(mBmpToCrop, (int) mBorderBound.left, (int) mBorderBound.top, (int) mBorderWidth,
(int) mBorderHeight);
}catch (Exception e){
Toast.makeText(getContext(), "图片格式无法剪切", Toast.LENGTH_SHORT).show();
e.printStackTrace();
}
return bitmap;
}
// Private Methods /////////////////////////////////////////////////////////
private void init(Context context) {
mBmpPaint = new Paint();
// 以下是抗锯齿
mBmpPaint.setAntiAlias(true);// 防止边缘的锯齿
mBmpPaint.setFilterBitmap(true);// 对位图进行滤波处理
mBorderPaint = new Paint();
mBorderPaint.setStyle(Style.STROKE);
mBorderPaint.setColor(Color.parseColor("#AAFFFFFF"));
mBorderPaint.setStrokeWidth(BORDER_LINE_WIDTH);
mGuidelinePaint = new Paint();
mGuidelinePaint.setColor(Color.parseColor("#AAFFFFFF"));
mGuidelinePaint.setStrokeWidth(1f);
mCornerPaint = new Paint();
mBgPaint = new Paint();
mBgPaint.setColor(Color.parseColor("#B0000000"));
mBgPaint.setAlpha(150);
}
private void setBmp() {
mBmpToCrop = BitmapFactory.decodeFile(mBmpPath);
mBmpBound = new RectF();
mBmpBound.left = BMP_LEFT;
mBmpBound.top = BMP_TOP;
mBmpBound.right = mBmpBound.left + mBmpToCrop.getWidth();
mBmpBound.bottom = mBmpBound.top + mBmpToCrop.getHeight();
// 使裁剪框一开始出现在图片的中心位置
mDefaultBorderBound = new RectF();
mDefaultBorderBound.left = (mBmpBound.left + mBmpBound.right - DEFAULT_BORDER_RECT_WIDTH) / 2;
mDefaultBorderBound.top = (mBmpBound.top + mBmpBound.bottom - DEFAULT_BORDER_RECT_HEIGHT) / 2;
mDefaultBorderBound.right = mDefaultBorderBound.left + DEFAULT_BORDER_RECT_WIDTH;
mDefaultBorderBound.bottom = mDefaultBorderBound.top + DEFAULT_BORDER_RECT_HEIGHT;
mBorderBound = new RectF();
mBorderBound.left = mDefaultBorderBound.left;
mBorderBound.top = mDefaultBorderBound.top;
mBorderBound.right = mDefaultBorderBound.right;
mBorderBound.bottom = mDefaultBorderBound.bottom;
getBorderEdgeLength();
invalidate();
}
private void drawBackground(Canvas canvas) {
/*-
-------------------------------------
| top |
-------------------------------------
| | | |<——————————mBmpBound
| | | |
| left | | right |
| | | |
| | <─┼───────┼────mBorderBound
-------------------------------------
| bottom |
-------------------------------------
*/
// Draw "top", "bottom", "left", then "right" quadrants.
// because the border line width is larger than 1f, in order to draw a complete border rect ,
// i have to change zhe rect coordinate to draw
float delta = BORDER_LINE_WIDTH / 2;
float left = mBorderBound.left - delta;
float top = mBorderBound.top - delta;
float right = mBorderBound.right + delta;
float bottom = mBorderBound.bottom + delta;
// -------------------------------------------------------------------------------移动到上下两端会多出来阴影
canvas.drawRect(mBmpBound.left, mBmpBound.top, mBmpBound.right, top, mBgPaint);
canvas.drawRect(mBmpBound.left, bottom, mBmpBound.right, mBmpBound.bottom, mBgPaint);
canvas.drawRect(mBmpBound.left, top, left, bottom, mBgPaint);
canvas.drawRect(right, top, mBmpBound.right, bottom, mBgPaint);
}
// 画裁剪区域中间的参考线
private void drawGuidlines(Canvas canvas) {
// Draw vertical guidelines.
final float oneThirdCropWidth = mBorderBound.width() / 3;
final float x1 = mBorderBound.left + oneThirdCropWidth;
canvas.drawLine(x1, mBorderBound.top, x1, mBorderBound.bottom, mGuidelinePaint);
final float x2 = mBorderBound.right - oneThirdCropWidth;
canvas.drawLine(x2, mBorderBound.top, x2, mBorderBound.bottom, mGuidelinePaint);
// Draw horizontal guidelines.
final float oneThirdCropHeight = mBorderBound.height() / 3;
final float y1 = mBorderBound.top + oneThirdCropHeight;
canvas.drawLine(mBorderBound.left, y1, mBorderBound.right, y1, mGuidelinePaint);
final float y2 = mBorderBound.bottom - oneThirdCropHeight;
canvas.drawLine(mBorderBound.left, y2, mBorderBound.right, y2, mGuidelinePaint);
}
private void onActionDown(float x, float y) {
}
private void onActionMove(float x, float y) {
float deltaX = x - mLastPoint.x;
float deltaY = y - mLastPoint.y;
// 这里先不考虑裁剪框放最大的情况
switch (touchPos) {
case POS_CENTER:
mBorderBound.left += deltaX;
// fix border position
if (mBorderBound.left < mBmpBound.left)
mBorderBound.left = mBmpBound.left;
if (mBorderBound.left > mBmpBound.right - mBorderWidth)
mBorderBound.left = mBmpBound.right - mBorderWidth;
mBorderBound.top += deltaY;
if (mBorderBound.top < mBmpBound.top)
mBorderBound.top = mBmpBound.top;
if (mBorderBound.top > mBmpBound.bottom - mBorderHeight)
mBorderBound.top = mBmpBound.bottom - mBorderHeight;
mBorderBound.right = mBorderBound.left + mBorderWidth;
mBorderBound.bottom = mBorderBound.top + mBorderHeight;
break;
case POS_TOP:
resetTop(deltaY);
break;
case POS_BOTTOM:
resetBottom(deltaY);
break;
case POS_LEFT:
resetLeft(deltaX);
break;
case POS_RIGHT:
resetRight(deltaX);
break;
case POS_TOP_LEFT:
resetTop(deltaY);
resetLeft(deltaX);
break;
case POS_TOP_RIGHT:
resetTop(deltaY);
resetRight(deltaX);
break;
case POS_BOTTOM_LEFT:
resetBottom(deltaY);
resetLeft(deltaX);
break;
case POS_BOTTOM_RIGHT:
resetBottom(deltaY);
resetRight(deltaX);
break;
default:
break;
}
invalidate();
}
private void onActionUp(float x, float y) {
}
private int detectTouchPosition(float x, float y) {
if (x > mBorderBound.left + TOUCH_FIELD && x < mBorderBound.right - TOUCH_FIELD
&& y > mBorderBound.top + TOUCH_FIELD && y < mBorderBound.bottom - TOUCH_FIELD)
return POS_CENTER;
if (x > mBorderBound.left + BORDER_CORNER_LENGTH && x < mBorderBound.right - BORDER_CORNER_LENGTH) {
if (y > mBorderBound.top - TOUCH_FIELD && y < mBorderBound.top + TOUCH_FIELD)
return POS_TOP;
if (y > mBorderBound.bottom - TOUCH_FIELD && y < mBorderBound.bottom + TOUCH_FIELD)
return POS_BOTTOM;
}
if (y > mBorderBound.top + BORDER_CORNER_LENGTH && y < mBorderBound.bottom - BORDER_CORNER_LENGTH) {
if (x > mBorderBound.left - TOUCH_FIELD && x < mBorderBound.left + TOUCH_FIELD)
return POS_LEFT;
if (x > mBorderBound.right - TOUCH_FIELD && x < mBorderBound.right + TOUCH_FIELD)
return POS_RIGHT;
}
// 前面的逻辑已经排除掉了几种情况 所以后面的 ┏ ┓ ┗ ┛ 边角就按照所占区域的方形来判断就可以了
if (x > mBorderBound.left - TOUCH_FIELD && x < mBorderBound.left + BORDER_CORNER_LENGTH) {
if (y > mBorderBound.top - TOUCH_FIELD && y < mBorderBound.top + BORDER_CORNER_LENGTH)
return POS_TOP_LEFT;
if (y > mBorderBound.bottom - BORDER_CORNER_LENGTH && y < mBorderBound.bottom + TOUCH_FIELD)
return POS_BOTTOM_LEFT;
}
if (x > mBorderBound.right - BORDER_CORNER_LENGTH && x < mBorderBound.right + TOUCH_FIELD) {
if (y > mBorderBound.top - TOUCH_FIELD && y < mBorderBound.top + BORDER_CORNER_LENGTH)
return POS_TOP_RIGHT;
if (y > mBorderBound.bottom - BORDER_CORNER_LENGTH && y < mBorderBound.bottom + TOUCH_FIELD)
return POS_BOTTOM_RIGHT;
}
return -1;
}
private void setLastPosition(MotionEvent event) {
mLastPoint.x = event.getX();
mLastPoint.y = event.getY();
}
private void getBorderEdgeLength() {
mBorderWidth = mBorderBound.width();
mBorderHeight = mBorderBound.height();
}
private void getBorderEdgeWidth() {
mBorderWidth = mBorderBound.width();
}
private void getBorderEdgeHeight() {
mBorderHeight = mBorderBound.height();
}
private void resetLeft(float delta) {
mBorderBound.left += delta;
getBorderEdgeWidth();
fixBorderLeft();
}
private void resetTop(float delta) {
mBorderBound.top += delta;
getBorderEdgeHeight();
fixBorderTop();
}
private void resetRight(float delta) {
mBorderBound.right += delta;
getBorderEdgeWidth();
fixBorderRight();
}
private void resetBottom(float delta) {
mBorderBound.bottom += delta;
getBorderEdgeHeight();
fixBorderBottom();
}
private void fixBorderLeft() {
// fix left
if (mBorderBound.left < mBmpBound.left)
mBorderBound.left = mBmpBound.left;
if (mBorderWidth < 2 * BORDER_CORNER_LENGTH)
mBorderBound.left = mBorderBound.right - 2 * BORDER_CORNER_LENGTH;
}
private void fixBorderTop() {
// fix top
if (mBorderBound.top < mBmpBound.top)
mBorderBound.top = mBmpBound.top;
if (mBorderHeight < 2 * BORDER_CORNER_LENGTH)
mBorderBound.top = mBorderBound.bottom - 2 * BORDER_CORNER_LENGTH;
}
private void fixBorderRight() {
// fix right
if (mBorderBound.right > mBmpBound.right)
mBorderBound.right = mBmpBound.right;
if (mBorderWidth < 2 * BORDER_CORNER_LENGTH)
mBorderBound.right = mBorderBound.left + 2 * BORDER_CORNER_LENGTH;
}
private void fixBorderBottom() {
// fix bottom
if (mBorderBound.bottom > mBmpBound.bottom)
mBorderBound.bottom = mBmpBound.bottom;
if (mBorderHeight < 2 * BORDER_CORNER_LENGTH)
mBorderBound.bottom = mBorderBound.top + 2 * BORDER_CORNER_LENGTH;
}
}