(裁剪图像)将裁剪矩形从缩放图像映射到原始图像

时间:2014-09-06 07:40:38

标签: android image-processing imageview

我正在尝试按照AOSP图库应用程序的源代码实现Android中的图像裁剪(实际代码来自此library)。我已将ImageView的比例类型设置为MATRIX,并使用图片矩阵上的posttranslatepostscale方法对图像进行缩放和翻译。

在图像上绘制固定为260x260像素的裁剪矩形,以ImageView为中心。此裁剪矩形的大小已固定,无法移动。相反,允许移动和缩放图像(放大/缩小),以便用户可以将所需的图像区域放在裁剪矩形内。

当用户将图片移动dxdy金额时,posttranslate(dx, dy)会在图片的矩阵上调用。然后通过调用matrix.map(rect)将裁剪矩形映射到当前矩阵。然后通过将dxdy转换为图像空间并相应地移动裁剪矩形来计算裁剪矩形的新位置(在原始图像上)。

这是移动图像的一些摘录:

// This matrix is recomputed when we go from the thumbnail image to
// the full size image.
protected Matrix baseMatrix = new Matrix();

// This is the supplementary transformation which reflects what
// the user has done in terms of zooming and panning.
//
// This matrix remains the same when we go from the thumbnail image
// to the full size image.
protected Matrix suppMatrix = new Matrix();

// This is the final matrix which is computed as the concatentation
// of the base matrix and the supplementary matrix.
private final Matrix displayMatrix = new Matrix();

//move image by dx dy
protected void panBy(float dx, float dy) {
    postTranslate(dx, dy);
    setImageMatrix(getImageViewMatrix());
}

 protected void postTranslate(float dx, float dy) {
    suppMatrix.postTranslate(dx, dy);
} 

// Combine the base matrix and the supp matrix to make the final matrix
protected Matrix getImageViewMatrix() {
    // The final matrix is computed as the concatentation of the base matrix
    // and the supplementary matrix
    displayMatrix.set(baseMatrix);
    displayMatrix.postConcat(suppMatrix);
    return displayMatrix;
}

这就是图像移动影响裁剪矩形视图的方式

public void handlePan(float dx, float dy)
{
   RectF r = computeLayout();

   float xDelta = (dx * (cropRect.width() / r.width()));
   float yDelta = -(dy * (cropRect.height() / r.height()));
   cropRect.offset(xDelta, yDelta);

   // Put the cropping rectangle inside image rectangle
   cropRect.offset(
           Math.max(0, imageRect.left - cropRect.left),
           Math.max(0, imageRect.top  - cropRect.top));

   cropRect.offset(
           Math.min(0, imageRect.right  - cropRect.right),
           Math.min(0, imageRect.bottom - cropRect.bottom));
}

private RectF computeLayout() {
    RectF r = new RectF(cropRect.left, cropRect.top,
                        cropRect.right, cropRect.bottom);
    matrix.mapRect(r);
    return r;
}

裁剪视图从以下matrix函数中获取图像的当前getunrotatedmatrix

 public Matrix getUnrotatedMatrix(){
    Matrix unrotated = new Matrix();
    getProperBaseMatrix(bitmapDisplayed, unrotated, false);
    unrotated.postConcat(suppMatrix);
    return unrotated;
}

 // Setup the base matrix so that the image is centered and scaled properly.
private void getProperBaseMatrix(RotateBitmap bitmap, Matrix matrix, boolean includeRotation) {
    float viewWidth = getWidth();
    float viewHeight = getHeight();

    float w = bitmap.getWidth();
    float h = bitmap.getHeight();
    matrix.reset();

    // We limit up-scaling to 3x otherwise the result may look bad if it's a small icon
    float widthScale = Math.min(viewWidth / w, 3.0f);
    float heightScale = Math.min(viewHeight / h, 3.0f);
    float scale = Math.min(widthScale, heightScale);

    if (includeRotation) {
        matrix.postConcat(bitmap.getRotateMatrix());
    }
    matrix.postScale(scale, scale);
    matrix.postTranslate((viewWidth  - w * scale) / 2F, (viewHeight - h * scale) / 2F);
}

这完美无缺。但我正在努力的是,处理图像的缩放。我已经尝试将矩形映射到矩阵,然后将此矩形映射到原始图像,按比例缩小裁剪矩形图像按比例放大,反之亦然。但它们都没有奏效。任何想法如何实现这一点(在图像视图中缩放图像后,获取原始图像(在SD卡上)裁剪矩形的位置)?缩放如下:

protected void zoomTo(float scaleFactor, float centerX, float centerY) {
    float oldScale = getScale();
    float scale = oldScale*scaleFactor;

    if (scale > maxZoom) {
        scale = maxZoom;
        scaleFactor=maxZoom/oldScale;
    }
    else if(scale<0.5)
    {
        scale=0.5f;
        scaleFactor=0.5f/oldScale;
    }

    suppMatrix.postScale(scaleFactor, scaleFactor, centerX, centerY);
    setImageMatrix(getImageViewMatrix());
}

据我所知,放大后裁剪矩形必须缩小(指向原始图像的较小区域),反之亦然。但是考虑到缩放的中心(即使在裁剪矩形之外,也可以是图像上的任何位置),如何准确地进行缩放并适当地定位裁剪矩形。

0 个答案:

没有答案