gpt4 book ai didi

android - 在android上调整位图大小的最有效内存方法?

转载 作者:IT老高 更新时间:2023-10-28 13:01:43 25 4
gpt4 key购买 nike

我正在构建一个图像密集型社交应用程序,其中图像从服务器发送到设备。当设备的屏幕分辨率较小时,我需要在设备上调整位图的大小以匹配其预期的显示尺寸。

问题是使用 createScaledBitmap在调整一大群缩略图图像的大小后,导致我遇到了很多内存不足的错误。

在 Android 上调整位图大小的最节省内存的方法是什么?

最佳答案

This answer is summarised from Loading large bitmaps Efficiently which explains how to use inSampleSize to load a down-scaled bitmap version.

In particular Pre-scaling bitmaps explains the details of various methods, how to combine them, and which are the most memory efficient.



在 Android 上调整位图大小的主要方法有 3 种,它们具有不同的内存属性:

createScaledBitmap API

此 API 将接收现有位图,并使用您选择的确切尺寸创建新位图。

从好的方面来说,您可以准确地获得您正在寻找的图像大小(无论它看起来如何)。但缺点是这个 API 需要一个 现有 位图才能工作。这意味着必须先加载、解码图像并创建位图,然后才能创建新的较小版本。这在获得确切尺寸方面是理想的,但在额外的内存开销方面很糟糕。因此,对于大多数倾向于内存意识的应用程序开发人员来说,这是一种交易破坏者

inSampleSize flag
BitmapFactory.Options有一个标记为 inSampleSize 的属性这将在解码时调整图像大小,以避免需要解码为临时位图。此处使用的这个整数值将以 1/x 缩小的尺寸加载图像。例如,设置 inSampleSize to 2 返回一半大小的图像,将其设置为 4 返回大小为 1/4 的图像。基本上图像尺寸总是比你的源尺寸小一些 2 的幂。

从内存的角度来看,使用 inSampleSize是一个非常快速的操作。实际上,它只会将图像的每个 Xth 像素解码为生成的位图。 inSampleSize 有两个主要问题虽然:
  • 它不会为您提供准确的分辨率 .它只会将位图的大小减小 2 的某个幂。
  • 它不会产生最佳质量的调整大小 .大多数调整大小的过滤器通过读取像素块,然后对它们进行加权以生成有问题的调整大小的像素来生成好看的图像。 inSampleSize通过每隔几个像素读取一次就可以避免这一切。结果是性能非常好,内存也很低,但质量会受到影响。

  • 如果您只是将图像缩小一些 pow2 大小,并且过滤不是问题,那么您找不到比 inSampleSize 更有效的内存(或性能)方法。 .

    inScaled, inDensity, inTargetDensity flags

    如果您需要将图像缩放到不等于 2 的幂的尺寸,那么您将需要 inScaled , inDensityinTargetDensity BitmapOptions 的旗帜.当 inScaled标志已设置,系统将通过划分 inTargetDensity 推导出应用于您的位图的缩放值。由 inDensity值。
    mBitmapOptions.inScaled = true;
    mBitmapOptions.inDensity = srcWidth;
    mBitmapOptions.inTargetDensity = dstWidth;

    // will load & resize the image to be 1/inSampleSize dimensions
    mCurrentBitmap = BitmapFactory.decodeResources(getResources(),
    mImageIDs, mBitmapOptions);

    使用这种方法将重新调整您的图像大小,并对其应用“调整大小过滤器”,也就是说,最终结果看起来会更好,因为在调整大小步骤中已经考虑了一些额外的数学运算。但请注意: 额外的过滤步骤,需要额外的处理时间 ,并且可以快速添加大图像,导致调整速度缓慢,并为过滤器本身分配额外的内存。

    由于额外的过滤开销,将这种技术应用于明显大于所需尺寸的图像通常不是一个好主意。

    魔法组合

    从内存和性能的角度来看,您可以组合这些选项以获得最佳结果。 (设置 inSampleSizeinScaledinDensityinTargetDensity 标志)
    inSampleSize将首先应用于图像,使其成为比目标尺寸大的下一个 2 的幂。然后, inDensity & inTargetDensity用于将结果缩放到您想要的精确尺寸,应用过滤操作来清理图像。

    结合这两者是一个更快的操作,因为 inSampleSize step 将减少生成的基于密度的 step 需要应用其调整大小过滤器的像素数。
    mBitmapOptions.inScaled = true;
    mBitmapOptions.inSampleSize = 4;
    mBitmapOptions.inDensity = srcWidth;
    mBitmapOptions.inTargetDensity = dstWidth * mBitmapOptions.inSampleSize;

    // will load & resize the image to be 1/inSampleSize dimensions
    mCurrentBitmap = BitmapFactory.decodeFile(fileName, mBitmapOptions);

    如果您需要将图像适合特定尺寸,并进行一些更好的过滤,那么此技术是获得正确尺寸的最佳桥梁,但可以通过快速、低内存占用的操作完成。

    获取图像尺寸

    在不解码整个图像的情况下获取图像大小
    为了调整位图的大小,您需要知道传入的尺寸。您可以使用 inJustDecodeBounds标志来帮助您获得图像的尺寸,而无需实际解码像素数据。
    // Decode just the boundaries
    mBitmapOptions.inJustDecodeBounds = true;
    BitmapFactory.decodeFile(fileName, mBitmapOptions);
    srcWidth = mBitmapOptions.outWidth;
    srcHeight = mBitmapOptions.outHeight;


    //now go resize the image to the size you want

    您可以先使用此标志对大小进行解码,然后计算适当的值以缩放到您的目标分辨率。

    关于android - 在android上调整位图大小的最有效内存方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32121058/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com