使用RenderScript在Android中旋转位图

15
当我使用以下代码时,会出现内存溢出异常。经过调查,RenderScript看起来是一个很好的选择。我在哪里可以找到类似操作的示例代码,并将其集成到我的项目中?

当我使用以下代码时,会出现内存溢出异常。经过调查,RenderScript看起来是一个很好的选择。我在哪里可以找到类似操作的示例代码,并将其集成到我的项目中?

public Bitmap rotateBitmap(Bitmap image, int angle) {
    if (image != null) {

        Matrix matrix = new Matrix();
        matrix.postRotate(angle, (image.getWidth()) / 2,
                (image.getHeight()) / 2);

        return Bitmap.createBitmap(image, 0, 0, image.getWidth(),
                image.getHeight(), matrix, true);
    }
    return null;
}

它是否总是返回outofmem?你的位图大小是多少? - Miloslaw Smyk
不是每次都会出现,但偶尔会。我认为这是由于复制品的创建所致。我使用Picasso库下载图像并将其调整大小以适应半屏幕大小。 - pats
@MiloslawSmyk 我的图像被降采样了,图像大小为110 KB,因此它相当小。有没有办法使用renderscript的ScriptInstric操作来实现这一点? - pats
@pats 你是在寻找90度旋转 - https://dev59.com/9mct5IYBdhLWcg3wgNjR 还是任意角度旋转(例如顺时针27度)的解决方案? - Morrison Chang
是的,我已经尝试过了。但是设置ScriptC非常困难。有没有一种方法可以在不设置ScriptC的情况下以90的倍数旋转。我的意思是只使用ScriptIntric和Java来实现。 - pats
2个回答

1
基本上旋转位图是一个旋转2D数组的任务,而不需要使用额外的内存。这是使用RenderScript的正确实现方式:Android: rotate image without loading it to memory
但是,如果您只是想显示旋转后的位图,则无需这样做。您可以简单地扩展ImageView并在绘制时旋转Canvas
canvas.save();
canvas.rotate(angle, X + (imageW / 2), Y + (imageH / 2));
canvas.drawBitmap(imageBmp, X, Y, null);
canvas.restore();

自带的RenderScript内核函数集合ScriptIntrinsic,包含了一些常见操作的函数,如:ScriptIntrinsic3DLUT、ScriptIntrinsicBLAS、ScriptIntrinsicBlend、ScriptIntrinsicBlur、ScriptIntrinsicColorMatrix、ScriptIntrinsicConvolve3x3、ScriptIntrinsicConvolve5x5、ScriptIntrinsicHistogram、ScriptIntrinsicLUT、ScriptIntrinsicResize和ScriptIntrinsicYuvToRGB。但是,它们目前并不包括旋转位图的功能,因此您需要创建自己的ScriptC脚本来实现。请注意,不要修改原有的函数。

谢谢,我已经尝试了链接中提出的rederscript算法。由于构建工具版本的混乱,设置scriptC的东西确实很困难。 我想知道是否有一种使用scriptinstric和javacode旋转的方法可以避免使用scriptC。 - pats

0

试试这段代码...

private Bitmap RotateImage(Bitmap _bitmap, int angle) {

    Matrix matrix = new Matrix();
    matrix.postRotate(angle);
    _bitmap = Bitmap.createBitmap(_bitmap, 0, 0, _bitmap.getWidth(), _bitmap.getHeight(), matrix, true);
    return _bitmap;
}

从相册选择图像时,请使用此代码。

像这样...

     File _file = new File(file_name);
     BitmapFactory.Options options = new BitmapFactory.Options();
     options.inSampleSize = 1;
     Bitmap bitmap = BitmapFactory.decodeFile(file_name, options);

     try {
            ExifInterface exif = new ExifInterface(file_name);
            int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, 1);
            if (orientation == ExifInterface.ORIENTATION_ROTATE_90) {
                bitmap = RotateImage(bitmap, 90);
            } else if (orientation ==ExifInterface.ORIENTATION_ROTATE_270) {
                bitmap = RotateImage(bitmap, 270);

            }

        } catch (Exception e) {
            e.printStackTrace();
        }
      image_holder.setImageBitmap(bitmap);

谢谢回复,但我没有看到太大的区别,因为在从方法返回新图像后,我将新图像分配给输入图像。 - pats
首先,您需要从前置摄像头捕获图像,然后使用此函数和不使用此函数进行检查。 - Vimal Gajera
哦,抱歉,我从互联网上下载了这张图片。 - pats
@pats 好的,当您从前置摄像头捕获图像时,会保存旋转后的图像,因此需要使用此功能。 - Vimal Gajera

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