处理大图像

时间:2016-05-24 06:08:15

标签: java android memory-mapped-files filechannel

我正在构建一个应用程序,我可以处理 10000X5000像素的超大图像。当我尝试在ImageView上显示此类图像时,应用程序崩溃了。 我无法进行位图采样,因为我无法改变图像的大小。

一项简单的工作是选择10000X5000像素的图像并将其显示在ImageView中。

目前,我正在使用简单的代码来实现此目的,应用程序正在崩溃。

            Uri selectedImage = data.getData();
            String[] filePathColumn = { MediaStore.Images.Media.DATA };

            // Get the cursor
            Cursor cursor = getContentResolver().query(selectedImage,
                    filePathColumn, null, null, null);
            // Move to first row
            cursor.moveToFirst();

            int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
            imgDecodableString = cursor.getString(columnIndex);
            cursor.close();
            ImageView imgView = (ImageView) findViewById(R.id.imgView);
            // Set the Image in ImageView after decoding the String



            imgView.setImageBitmap(BitmapFactory
                    .decodeFile(imgDecodableString));

Exception是OutOfMemory

  

E / AndroidRuntime:致命异常:主要                                                                                     流程:com.example.star.largeiamgesdemo,

     PID:21155                                                                                     java.lang.OutOfMemoryError:无法分配200000012字节   分配4194208个空闲字节和123MB直到OOM

MemoryMapFile之类的东西可以做到这一点,但文件没有为FileChannel

中的图片获取任何内容

更新

我无法缩小图像,同时显示因为我必须编辑它们(即用户可以在图像上写一些东西,或将其他图像作为水印放在它们上面)

由于

3 个答案:

答案 0 :(得分:3)

正如你所说:

  

我无法进行位图采样,因为我无法改变图像的大小。

所以,减少图像大小或在显示之前对其进行采样,是不行的。我认为下面是一个解决方案。

由于Android的dalvik限制,您可以使用最大堆大小。超过它时,发生崩溃。

为了绕过dalvik限制,您可以使用jni从本机堆中申请内存。您必须在jni中使用or。您可以在SurfaceView上选择显示图像,然后通过libjpeg获取Surface对象,将其传递给jni,然后使用holder.getSurface() lib解码图像并显示它。接下来是一些示例代码,调用libjpeg函数来显示大图像。

showJPG()

希望能帮到你!

答案 1 :(得分:0)

很明显,您必须缩小图片尺寸,否则您的手机无法呈现图片以显示在ImageView中。因此,您需要缩小图像,以便可以在ImageView

中显示图像
int imageScaleWidth = 480; // Change the width
Bitmap bitmapImage = BitmapFactory.decodeFile(imgDecodableString); // imgDecodableString is your image path.
int imageScaleHeigth = (int) ( bitmapImage.getHeight() * (imageScaleWidth  / bitmapImage.getWidth()) );
Bitmap scaled = Bitmap.createScaledBitmap(bitmapImage, imageScaleWidth , imageScaleHeigth , true);
imgView.setImageBitmap(scaled);

答案 2 :(得分:0)

您应该阅读"高效加载大型位图"

上的Android文档

特别是,你提到你不能用于"位图采样"但请注意,Android允许您读取图像文件大小,然后计算适用于可用大小的采样。 Android将只加载采样位图,这很好,因为屏幕分辨率不足以正确显示这样的图像。

另外,请务必考虑方法decodeSampledBitmapFromResource以获取缩略图。

https://developer.android.com/training/displaying-bitmaps/load-bitmap.html#load-bitmap

最后,如果需要,请务必使用largeHeap Manifest属性 - 并根据文档查看其他内存优化技术:

https://developer.android.com/training/articles/memory.html