如何调整流的位图的就地无一读的整体形象?位图、一读、形象

2023-09-12 07:14:20 作者:可望不可及

我有一个Android应用程序,这是非常形象密集。我目前使用的Bitmap.createScaledBitmap()给图像缩放到期望的尺寸。然而,这种方法要求我已经在存储器中的原始位图,它可以是相当可观的。

I have an Android application that is very image intensive. I'm currently using Bitmap.createScaledBitmap() to scale the image to a desired size. However, this method requires that I already have the original bitmap in memory, which can be quite sizable.

我如何可以扩展的,我下载不先写了整个事情给当地的内存或文件系统?

How can I scale a bitmap that I'm downloading without first writing the entire thing out to local memory or file system?

推荐答案

此方法将读取图像的头信息,以确定其大小,然后读取形象和到位而不用于分配内存也扩展到所需的大小完整的原始尺寸的图像。

This method will read the header information from the image to determine its size, then read the image and scale it to the desired size in place without allocating memory for the full original sized image.

它还使用BitmapFactory.Options.inPurgeable,这似乎是使用大量位图时是一个稀疏文件,但可取的办法,以prevent OOM异常。 更新:不再使用inPurgeable,请参阅this注意从罗曼的

It also uses BitmapFactory.Options.inPurgeable, which seems to be a sparsely documented but desirable option to prevent OoM exceptions when using lots of bitmaps. UPDATE: no longer uses inPurgeable, see this note from Romain

它的工作原理使用的BufferedInputStream通过InputStream中读取整个图像之前读了图像的头信息。

It works by using a BufferedInputStream to read the header information for the image before reading the entire image in via the InputStream.

/**
 * Read the image from the stream and create a bitmap scaled to the desired
 * size.  Resulting bitmap will be at least as large as the 
 * desired minimum specified dimensions and will keep the image proportions 
 * correct during scaling.
 */
protected Bitmap createScaledBitmapFromStream( InputStream s, int minimumDesiredBitmapWith, int minimumDesiredBitmapHeight ) {

    final BufferedInputStream is = new BufferedInputStream(s, 32*1024);
    try {
        final Options decodeBitmapOptions = new Options();
        // For further memory savings, you may want to consider using this option
        // decodeBitmapOptions.inPreferredConfig = Config.RGB_565; // Uses 2-bytes instead of default 4 per pixel

        if( minimumDesiredBitmapWidth >0 && minimumDesiredBitmapHeight >0 ) {
            final Options decodeBoundsOptions = new Options();
            decodeBoundsOptions.inJustDecodeBounds = true;
            is.mark(32*1024); // 32k is probably overkill, but 8k is insufficient for some jpgs
            BitmapFactory.decodeStream(is,null,decodeBoundsOptions);
            is.reset();

            final int originalWidth = decodeBoundsOptions.outWidth;
            final int originalHeight = decodeBoundsOptions.outHeight;

            // inSampleSize prefers multiples of 2, but we prefer to prioritize memory savings
            decodeBitmapOptions.inSampleSize= Math.max(1,Math.min(originalWidth / minimumDesiredBitmapWidth, originalHeight / minimumDesiredBitmapHeight));

        }

        return BitmapFactory.decodeStream(is,null,decodeBitmapOptions);

    } catch( IOException e ) {
        throw new RuntimeException(e); // this shouldn't happen
    } finally {
        try {
            is.close();
        } catch( IOException ignored ) {}
    }

}