android捏和以编程方式从imageview裁剪图像

时间:2014-07-30 13:43:28

标签: android bitmap imageview crop pinchzoom

我有一个要求,比如在图像视图中显示位图并提供捏合。如果需要然后从android中的imageview裁剪可见图像。为此,我找到了这样的解决方案,它可以帮助至少一个开发人员。

public class PinchImageView extends ImageView implements OnTouchListener {
private Context mContext;
private float MAX_SCALE = 4f;

private Matrix mMatrix;
private final float[] mMatrixValues = new float[9];

// display width height.
private int mWidth;
private int mHeight;

private int mIntrinsicWidth;
private int mIntrinsicHeight;

private float mScale;
private float mMinScale;

private float mPrevDistance;
private boolean isScaling;

private int mPrevMoveX;
private int mPrevMoveY;
private GestureDetector mDetector;

String TAG = "PinchImageView ";

private boolean temp ;

public PinchImageView (Context context, AttributeSet attr) {
    super(context, attr);
    this.mContext = context;
    initialize();
}

public PinchImageView (Context context) {
    super(context);
    this.mContext = context;
    initialize();
}

@Override
public void setImageBitmap(Bitmap bm) {
    super.setImageBitmap(bm);
    this.initialize();
}

@Override
public void setImageResource(int resId) {
    super.setImageResource(resId);
    this.initialize();
}

private void initialize() {

    this.setScaleType(ScaleType.MATRIX);
    this.mMatrix = new Matrix();
    Drawable d = getDrawable();
    if (d != null) {
        mIntrinsicWidth = d.getIntrinsicWidth();
        mIntrinsicHeight = d.getIntrinsicHeight();
        setOnTouchListener(this);
    }
    mDetector = new GestureDetector(mContext, new GestureDetector.SimpleOnGestureListener() {
        @Override
        public boolean onDoubleTap(MotionEvent e) {
            maxZoomTo((int) e.getX(), (int) e.getY());
            cutting();
            return super.onDoubleTap(e);
        }
    });

}

@Override
protected boolean setFrame(int l, int t, int r, int b) {

    mWidth = r - l;
    mHeight = b - t;
    mMatrix.reset();
    int r_norm = r - l;
    mScale = (float) r_norm / (float) mIntrinsicWidth;

    int paddingHeight = 0;
    int paddingWidth = 0;
    // scaling vertical
    if (mScale * mIntrinsicHeight > mHeight) {
        mScale = (float) mHeight / (float) mIntrinsicHeight;
        mMatrix.postScale(mScale, mScale);
        paddingWidth = (r - mWidth) / 2;
        paddingHeight = 0;
        // scaling horizontal
    } else {
        mMatrix.postScale(mScale, mScale);
        paddingHeight = (b - mHeight) / 2;
        paddingWidth = 0;
    }
    mMatrix.postTranslate(paddingWidth, paddingHeight);

    setImageMatrix(mMatrix);
    mMinScale = mScale;
    zoomTo(mScale, mWidth / 2, mHeight / 2);
    cutting();
    return super.setFrame(l, t, r, b);
}

protected float getValue(Matrix matrix, int whichValue) {
    matrix.getValues(mMatrixValues);
    return mMatrixValues[whichValue];
}

protected float getScale() {
    return getValue(mMatrix, Matrix.MSCALE_X);
}

public float getTranslateX() {
    return getValue(mMatrix, Matrix.MTRANS_X);
}

protected float getTranslateY() {
    return getValue(mMatrix, Matrix.MTRANS_Y);
}

protected void maxZoomTo(int x, int y) {
    if (mMinScale != getScale() && (getScale() - mMinScale) > 0.1f) {
        // threshold 0.1f
        float scale = mMinScale / getScale();
        zoomTo(scale, x, y);
    } else {
        float scale = MAX_SCALE / getScale();
        zoomTo(scale, x, y);
    }
}

public void zoomTo(float scale, int x, int y) {
    if (getScale() * scale < mMinScale) {
        return;
    }
    if (scale >= 1 && getScale() * scale > MAX_SCALE) {
        return;
    }
    mMatrix.postScale(scale, scale);
    // move to center
    mMatrix.postTranslate(-(mWidth * scale - mWidth) / 2, -(mHeight * scale - mHeight) / 2);

    // move x and y distance
    mMatrix.postTranslate(-(x - (mWidth / 2)) * scale, 0);
    mMatrix.postTranslate(0, -(y - (mHeight / 2)) * scale);
    setImageMatrix(mMatrix);
}

public void cutting() {
    temp=true;
    int width = (int) (mIntrinsicWidth * getScale());
    int height = (int) (mIntrinsicHeight * getScale());
    if (getTranslateX() < -(width - mWidth)) {
        mMatrix.postTranslate(-(getTranslateX() + width - mWidth), 0);
    }
    if (getTranslateX() > 0) {
        mMatrix.postTranslate(-getTranslateX(), 0);

    }
    if (getTranslateY() < -(height - mHeight)) {
        mMatrix.postTranslate(0, -(getTranslateY() + height - mHeight));

    }
    if (getTranslateY() > 0) {
        mMatrix.postTranslate(0, -getTranslateY());

    }
    if (width < mWidth) {
        mMatrix.postTranslate((mWidth - width) / 2, 0);

    }
    if (height < mHeight) {
        mMatrix.postTranslate(0, (mHeight - height) / 2);

    }
    Log.e("@@@@@@@@", ""+mMatrix);

    setImageMatrix(mMatrix);
}

private float distance(float x0, float x1, float y0, float y1) {
    float x = x0 - x1;
    float y = y0 - y1;
    return FloatMath.sqrt(x * x + y * y);
}

private float dispDistance() {
    return FloatMath.sqrt(mWidth * mWidth + mHeight * mHeight);
}

@Override
public boolean onTouchEvent(MotionEvent event) {
    if (mDetector.onTouchEvent(event)) {
        return true;
    }
    int touchCount = event.getPointerCount();
    switch (event.getAction()) {
    case MotionEvent.ACTION_DOWN:
    case MotionEvent.ACTION_POINTER_1_DOWN:
    case MotionEvent.ACTION_POINTER_2_DOWN:
        if (touchCount >= 2) {
            float distance = distance(event.getX(0), event.getX(1), event.getY(0), event.getY(1));
            mPrevDistance = distance;
            isScaling = true;
        } else {
            mPrevMoveX = (int) event.getX();
            mPrevMoveY = (int) event.getY();
        }
    case MotionEvent.ACTION_MOVE:
        if (touchCount >= 2 && isScaling) {
            float dist = distance(event.getX(0), event.getX(1), event.getY(0), event.getY(1));
            float scale = (dist - mPrevDistance) / dispDistance();
            mPrevDistance = dist;
            scale += 1;
            scale = scale * scale;
            zoomTo(scale, mWidth / 2, mHeight / 2);
            cutting();
        } else if (!isScaling) {

            int distanceX = mPrevMoveX - (int) event.getX();
            int distanceY = mPrevMoveY - (int) event.getY();
            mPrevMoveX = (int) event.getX();
            mPrevMoveY = (int) event.getY();
            mMatrix.postTranslate(-distanceX, -distanceY);
            cutting();
        }
        break;
    case MotionEvent.ACTION_UP:
    case MotionEvent.ACTION_POINTER_UP:
    case MotionEvent.ACTION_POINTER_2_UP:
        if (event.getPointerCount() <= 1) {
            isScaling = false;
        }
        break;
    }
    return true;
}

@Override
public boolean onTouch(View v, MotionEvent event) {
    return super.onTouchEvent(event);
}}

在自定义视图中使用PinchImageView类,在android中使用imageview。并从PinchImageView获取可见(图像)位图在PinchImageView类中添加以下方法。

    public Bitmap getCroppedImage(ImageView imageView) {
    // TODO Auto-generated method stub

        BitmapDrawable drawable = (BitmapDrawable)getDrawable();
        int width = drawable.getBitmap().getWidth();
        int height = drawable.getBitmap().getHeight();
        Bitmap cropedBitmap=drawable.getBitmap();
        Canvas comboImage = new Canvas(cropedBitmap);
        Bitmap background = Bitmap.createScaledBitmap(drawable.getBitmap(),width, height, true);

    comboImage.drawBitmap(background, mMatrix, null);

    return cropedBitmap;

}

示例:在您的XML布局中添加了ImageView

的内容
   <com.packagename.genric.PinchImageView 
                android:id="@+id/pinchimageView "
                android:layout_width="match_parent"
                android:layout_height="match_parent"/>

和您的活动

    PinchImageView  _pinchimageview =(PinchImageView)findViewById(R.id.pinchimageView);

设置图片

  _pinchimageview .setImageBitmap(bitmap);
  _pinchimageview .setImageResource(R.drawable.ic_launcher);

0 个答案:

没有答案