机器人:关于位图,内存使用情况和缩放位图、缩放、机器人、内存

2023-09-05 07:20:01 作者:不努力,拿什么说明天

对于可读性,我贴我的解决方案是指第一个code的例子,并与Theni上市我的解决方案的说明中数值列表。的

我一直在努力奋斗着这个有一段时间了。我已经做了很多的阅读,就问这里的问题,并尝试;但还没有拿出一个体面的解决办法。我需要从输入流读取各种大小的图像,并以高品质作为我的记忆条件允许的显示出来。下面是我考虑的选项,其中没有一个似乎对我很好。任何帮助或投入将大大AP preciated。

 公共类NativeTest扩展活动
 {
    @覆盖
    公共无效的onCreate(包savedInstanceState)
    {
       super.onCreate(savedInstanceState);
       双nativeUsage = Debug.getNativeHeapAllocatedSize();
       Log.i(记忆,nativeUsage +);
    }
 }


 双getAvailableMemory()
 {
    //当前堆大小
     。双HEAPSIZE =调用Runtime.getRuntime()totalMemory();
    //堆可用量
    双老天premaining =调用Runtime.getRuntime()freeMemory()。
    双nativeUsage = Debug.getNativeHeapAllocatedSize();
     双memoryAvailable =调用Runtime.getRuntime()maxMemory() - (HEAPSIZE  -  HEA premaining) -  nativeUsage。
    返回memoryAvailable;
 }

位图createImageTrialAndError(InputStream的流)
{
    位图图像= NULL;
    INT dowsample = 1;
    而(图像== NULL)
    {
       尝试
       {
        选项​​选择采用=新的选项();
        opts.inSampleSize = downsample的;
        图像= BitmapFactory.de codeStream(imgStream,空,选择采用);
       }
       赶上(OutOfMemoryError异常OME)
       {
           下采样=下采样* 2;
           Log.i(出纪念品的,请尝试使用+下采样);
       }
    }

    返回形象;
}
 

理想的解决方案是,如果位图有Bitmap.drawBitmap(InputStream中...)方法。这将让我从InputStream画,而不必分配内存的位图。唉,这不是一个选项。 根据可用内存缩放位图。这涉及检索位图的宽度和高度,计算位图需要为宽*高* 4 ,计算的可用内存,然后 BitmapFactory.Options.inSampleSize 这样的位图将使用较少的内存比什么是可用的。但是,此选项失败,因为我一直没能找到一个远程可靠的方法来计算的可用内存。下面的getAvailableMemory()方法看起来像它应该工作:它计算可用内存最大内存 - 在Java堆使用的内存 - 在本机堆使用的内存。 不幸的是,这个公式给出非常不可靠的结果。主要是因为 Debug.getNativeHeapAllocatedSize()不出现是位图的内存使用情况的准确再presentation。其误差的一个明显的例子是NativeTest活动,下文。在我的三星Galaxy平板电脑,输出的日志声明:3759416.0。 3.75 MB本机分配一个空的活动,显然不是一个可靠的方法来确定位图缩放。 在开始与一个缩放因子,并尝试初始化位图;如果初始化失败,因为内存,两倍的比例因子,然后再试一次;重复这个过程,直到成功。这是由 createBitmapTrialAndError说明()。这实际上是出奇的有效,并不十分缓慢。然而,这是非常不可取的,因为我在我的应用程序的其他地方使用SoftReferences,而运行内存迫使这些SoftReferences的集合,其中有一个显著的性能影响。那将是更期望知道适当的缩放因子最初,这将避免这些SoftReferences的不必要集合。 在我的最终解决方案似乎有点可疑。基本上,它结合了2及3,但不使用 Debug.getNativeAllocatedSize()。相反,我跟踪我自己的位图的内存分配,通过跟踪在任何地方我分配位图和清点自己的内存使用情况,再减去我回收任何位图的内存使用情况。我代替nativeUsage中getAvailableMemory()的使用此值,为了计算正确的比例因子为位图。并且在该一个内存溢出异常发生在使用这种方法的情况下,我使用溶液3作为后备的方式来计算可接受的尺度。与此明显的问题是试图跟踪我自己的本机内存使用情况的大规模sketchyness,但对我来说,这似乎是最好的解决办法。 解决方案

正确的做法是要脱code,你需要表现出与二次采样在瓷砖的形象,当你需要放大尺寸。

还有,应该正是这样做的库,检查出来: https://github.com/davemorrissey/subsampling-scale-image-view

For readibility, I posted the code examples that my solutions refer to first, and thenI listed the explanations of my solutions in a numerical list.

299元起的官方扩容服务 良心但不值得

I have been struggling with this for a while now. I have done much reading, asked questions on here, and experimented; but have not come up with a decent solution. I need to read variously sized images from input streams, and display them with as high of quality as my memory constraints allow. Below are the options I have considered, none of which seem great to me. Any help or input would be greatly appreciated.

 public class NativeTest extends Activity
 {
    @Override
    public void onCreate(Bundle savedInstanceState) 
    {
       super.onCreate(savedInstanceState);
       double nativeUsage = Debug.getNativeHeapAllocatedSize(); 
       Log.i("memory", nativeUsage+"");
    } 
 }


 double getAvailableMemory()
 {
    //current heap size 
     double heapSize =  Runtime.getRuntime().totalMemory();
    //amount available in heap 
    double heapRemaining = Runtime.getRuntime().freeMemory();   
    double nativeUsage  =  Debug.getNativeHeapAllocatedSize();
     double memoryAvailable = Runtime.getRuntime().maxMemory() - (heapSize - heapRemaining) - nativeUsage;
    return memoryAvailable;
 }

Bitmap createImageTrialAndError(InputStream stream)
{
    Bitmap image = null;
    int dowsample = 1;
    while(image == null)
    {
       try
       {    
        Options opts = new Options();
        opts.inSampleSize =  downsample;
        image = BitmapFactory.decodeStream(imgStream, null, opts);
       }
       catch (OutOfMemoryError ome)
       {
           downsample = downsample * 2;
           Log.i("out of mem", "try using: " + downsample); 
       }
    }

    return image;
}

The ideal solution would be if Bitmap had a Bitmap.drawBitmap(inputstream...) method. This would allow me to draw from the inputstream without having to allocate memory for the Bitmap. Alas, this is not an option. Scale the Bitmap according to memory available. This involves retrieving the width and height of the Bitmap, calculating the number of bytes Bitmap requires as width * height * 4, calculating the available memory, and then BitmapFactory.Options.inSampleSize such that the Bitmap will use less memory than what is available. However, this option fails because I have not been able to find a remotely reliable way to calculate the available memory. The getAvailableMemory() method below seems like it should work: it calculates available memory as maximum memory - memory used in the java heap - memory used in the native heap. Unfortunately, this formula gives very unreliable results. Mainly because Debug.getNativeHeapAllocatedSize() does not appear to be an accurate representation of Bitmap memory usage. One obvious example of its inaccuracy is the NativeTest Activity, below. On my Samsung Galaxy tablet, the log statement outputted is: 3759416.0. 3.75 mb of native allocation for an empty activity, clearly not a reliable way to determine bitmap scaling. Start with a scaling factor of one, and try to initialize the Bitmap; if the initialization fails due to memory, double the scaling factor and try again; and repeat this process until successful. This is illustrated by createBitmapTrialAndError(). This is actually surprisingly effective and not terribly slow. However, it is very undesirable because I use SoftReferences elsewhere in my application, and running out of memory forces the collection of these SoftReferences, which has a significant performance impact. It would be much more desirable to know the proper scaling factor initially, which would avoid the unnecessary collection of these SoftReferences. My final solution seems a bit questionable. Basically it combines 2 & 3, but doesn’t use Debug.getNativeAllocatedSize(). Instead, I track my own Bitmap memory allocation, by tracking anywhere I allocate Bitmaps and tallying their memory usage, and then subtracting the memory usage of any Bitmaps that I recycle. I use this value in place of the nativeUsage in getAvailableMemory(), in order to calculate the proper scaling factor for the Bitmaps. And in the event that an Out Of Memory exception occurs in using this method, I use solution 3 as a fallback way to calculate an acceptable scale. The obvious problem with this is the massive sketchyness of trying to track my own native memory usage but, to me, it seems to be the best solution.

解决方案

The right approach is to decode for the size you need to show and subsample the image in tiles when you need to zoom.

There's a library that should do exactly this, check it out: https://github.com/davemorrissey/subsampling-scale-image-view