Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android: Slow performance using a big image in ImageView

I have an Activity where I have a background image in an ImageView, and nine transparent buttons on top of the image.

http://i.stack.imgur.com/GGQqd.png

When I tap any of the buttons I make a RelativeLayout appears in the top of the background.

http://i.stack.imgur.com/JvKQK.jpg

The problem is: When I use a big resolution image as a background in the layout the performance is very poor.

I'm using a PNG image of 2048 x 1536, and it's weight is about 500k. When I use a smaller image like 1024 x 768 the application works fine, but it looks terrible.

Is there a restriction or a method to use big images without losing performance?

like image 761
Diego Alejandro Ossa Avatar asked Jul 21 '15 18:07

Diego Alejandro Ossa


2 Answers

That bitmap is huge. The 500k you mention is the compressed size. Images are uncompressed in memory when you use them. You're actually looking at 2048×1536×4 = 12582912 = over 12MB of memory use.

If you're on a device like Nexus 9 that has that screen resolution, then you can reasonably assume it also has the memory, GPU and bus bandwidth to deal with an image of that size. However, if you're on a lower resolution device (most devices are, keep in mind that even Full HD is just 65% as large), then this image is phenomenally wasteful of memory. You can buy low end devices today with a 240x320 screen, where a full screen bitmap is a mere 2.5% the size of your image.

You're going to have to scale that image when you load it. Use BitmapFactory.Options to set the desired size before loading the image.

Furthermore, you're putting text directly on top of it. Text rendering requires alpha transparency, which requires sampling the underlying image. If you can put the text on an opaque background and put that on top, you'll save some GPU load as well, but I'm actually not sure how much performance that's going to get you. It may not be so big a deal.

like image 148
Barend Avatar answered Nov 12 '22 22:11

Barend


You can use Dave Morissey's Subsampling Scale Image View as a drop in replacement of the standard image view.

XML layout:

<com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView
                    android:layout_width="match_parent"
                    android:layout_height="match_parent" 
                    android:scaleType="fitXY"
                    android:id="@+id/photo"/>
            </RelativeLayout>

Set image in code and disable touch:

photo = (SubsamplingScaleImageView) view.findViewById(R.id.photo);
photo.setOnTouchListener(new View.OnTouchListener() {
                            @Override
                            public boolean onTouch(View v, MotionEvent event) {
                                return true;
                            }
                        });
photo.setImage(ImageSource.uri(Uri.fromFile(new File("/somepath/file.png"))));

build.gradle:

compile 'com.davemorrissey.labs:subsampling-scale-image-view:3.6.0'

like image 1
Boris Treukhov Avatar answered Nov 12 '22 21:11

Boris Treukhov