在安卓上转换原始位图

5

所以,我正在使用这个库https://github.com/thuytrinh/android-collage-views为我的ImageView添加“MultiTouchListener”功能。基本上,我允许用户使用旋转、缩放和平移来修改照片以满足他的需求。现在唯一的问题是如何保存它。我是这样做的:

    Bitmap bitmap = Bitmap.createBitmap(imageContainer.getWidth(), imageContainer.getHeight(), Bitmap.Config.ARGB_8888);
    Canvas canvas = new Canvas(bitmap);
    canvas.drawColor(Color.WHITE);
    imageContainer.draw(canvas);

代码可以正常运行,但是由于图片大小与手机屏幕分辨率相关,导致图片不够大。我想对给定的位图进行完整尺寸的变换,并且希望变换后的图片看起来像在屏幕上一样(因此需要裁剪屏幕外的所有内容)。

我尝试了以下方法:

    Bitmap newBitmap = Bitmap.createBitmap(image.getWidth(), image.getHeight(), Bitmap.Config.ARGB_8888);
    Canvas canvas = new Canvas(newBitmap);
    canvas.drawColor(Color.WHITE);
    Paint paint = new Paint();
    paint.setAntiAlias(true);
    canvas.drawBitmap(image, imageView.getMatrix(), paint);

但是它看起来不像预期那样。

用户屏幕:

输入图片描述

输出图像(没有裁剪,因为我不知道应该从哪一侧进行裁剪):

输入图片描述

怎样才能解决这个问题?有什么解决方法吗?

1个回答

4

这里有一种方法可以实现,虽然不完美但应该能给你一个良好的起点:

在这个过程中,container 指的是包含转换后的 ImageView 的视图,也就是你截图中的手机壳,而 src 则是原始的源位图。

  • 首先,您需要计算所需的输出位图的宽度和高度,即使图像适合其中并保持容器的比率:

    float containerWidth = containerView.getWidth();
    float containerHeight = containerView.getHeight();
    
    float srcWidth = src.getWidth();
    float srcHeight = src.getHeight();
    
    float containerRatio = containerWidth / containerHeight;
    float srcRatio = srcWidth / srcHeight;
    
    float outputWidth, outputHeight;
    
    if(srcRatio > containerRatio) { //适合宽度
            outputWidth = srcWidth;
            outputHeight = srcWidth / containerRatio;
    }
    else if(srcRatio < containerRatio) { //适合高度
            outputHeight = srcHeight;
            outputWidth = srcHeight * containerRatio;
    }
    else {
        outputWidth = srcWidth;
        outputHeight = srcHeight;
    }
    
  • 将容器宽度/高度和输出宽度/高度之间的比率应用于保存用户所做转换的矩阵的翻译部分

    float containerToOutputRatioWidth = outputWidth / containerWidth;
    float containerToOutputRatioHeight = outputHeight / containerHeight;
    
    float[] values = new float[9];
    transformedImageView.getMatrix().getValues(values);
    values[2] = values[2] * containerToOutputRatioWidth;
    values[5] = values[5] * containerToOutputRatioHeight;
    Matrix outputMatrix = new Matrix();
    outputMatrix.setValues(values);
    
  • 使用正确的大小(outputWidth,outputHeight)和矩阵(outputMatrix)绘制输出位图。

    Bitmap newBitmap = Bitmap.createBitmap(Math.round(outputWidth), Math.round(outputHeight), Bitmap.Config.ARGB_8888);
    Canvas canvas = new Canvas(newBitmap);
    canvas.drawColor(Color.WHITE);
    Paint paint = new Paint();
    paint.setAntiAlias(true);
    canvas.drawBitmap(src, outputMatrix, paint);
    

Demo.

警告

在内存分配方面要小心,这段代码将导致分配一些大型位图,您应该实现一些与您的需求相适应的限制。(同时在后台进行分配和绘制)

根据您最初放置图像的位置,您可能需要进行一些调整。


感谢您详细的回答!我尝试了您的方法,但是输出的位图不在正确的位置。请查看我的代码:http://pastebin.com/6e0KEEBz。您可以轻松地在我的旧方法和您的方法之间切换以查看输出。 - Makalele
没有您的布局和资源文件,这个内容有点不相关。在这里,我提供了一个更完整且易于运行的代码版本:https://gist.github.com/meynety/387d01570be2066c2b68。正如我在答案中所说,根据您的布局,您可能需要进行一些调整... - meynety
是的,你的代码很好用。我找到了问题所在——它是imageView的大小设置——这使它看起来不同。我只是删除了那一行。现在我正在努力完成最后一步——让初始图像看起来像填充(在初始加载照片后没有空白空间)。我尝试在你的示例中使用android:scaleType="centerCrop",但它没有任何作用。 - Makalele
正如我所说,代码需要根据您最初放置图像的方式进行一些调整(适用于fitStart),这可能是因为ImageView#getMatrix()仅包含视图的变换,而不包括视图内部的可绘制对象。稍后我会给您发布一些代码。还要注意adjustViewBounds="true" - meynety
是的,我已经添加了adjustViewBounds。期待你的代码 :) - Makalele

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接