我正在尝试按照AOSP图库应用程序的源代码实现Android中的图像裁剪(实际代码来自此library)。我已将ImageView
的比例类型设置为MATRIX
,并使用图片矩阵上的posttranslate
和postscale
方法对图像进行缩放和翻译。
在图像上绘制固定为260x260像素的裁剪矩形,以ImageView
为中心。此裁剪矩形的大小已固定,无法移动。相反,允许移动和缩放图像(放大/缩小),以便用户可以将所需的图像区域放在裁剪矩形内。
当用户将图片移动dx
,dy
金额时,posttranslate(dx, dy)
会在图片的矩阵上调用。然后通过调用matrix.map(rect)
将裁剪矩形映射到当前矩阵。然后通过将dx
,dy
转换为图像空间并相应地移动裁剪矩形来计算裁剪矩形的新位置(在原始图像上)。
这是移动图像的一些摘录:
// 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());
}
据我所知,放大后裁剪矩形必须缩小(指向原始图像的较小区域),反之亦然。但是考虑到缩放的中心(即使在裁剪矩形之外,也可以是图像上的任何位置),如何准确地进行缩放并适当地定位裁剪矩形。