An image view loading long graph for Android

Keywords: Mobile Android less

Some apps may make a lot of content into a high-definition picture to the mobile terminal for loading (our project is...), if the picture is small, it's OK, but if the picture is too large (we have more than 2M, MMP), it's either not displayed, or it's not always fuzzy. So what should we do? Use BitmapRegionDecoder to segment and then splice the pictures.

 

Large picture display.gif

Take the picture in this paper as an example. The height is 6543. If you want to segment in 3000, you need to generate two 3000 bitmaps plus one 543 bitmap.

String url = "http://bmob-cdn-15177.b0.upaiyun.com/2018/08/23/8fa7f1c2404bafbd808bde10ff072ceb.jpg";
Glide.with(this).load(url)
                .asBitmap()
                .into(new SimpleTarget<Bitmap>() {
                    @Override
                    public void onResourceReady(Bitmap resource, GlideAnimation<? super Bitmap> glideAnimation) {
                        setBitmapToImg(resource);
                    }
                });

private void setBitmapToImg(Bitmap resource) {
        try {
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            resource.compress(Bitmap.CompressFormat.PNG, 100, baos);

            InputStream isBm = new ByteArrayInputStream(baos.toByteArray());

            //BitmapRegionDecoder newInstance(InputStream is, boolean isShareable)
            //It is used to create BitmapRegionDecoder. isBm represents input stream, which is only supported by jpeg and png pictures.
            // If isShareable is true, BitmapRegionDecoder will maintain a surface reference to the input stream.
            // If false, it creates a copy of the input stream and uses it all the time. Even if true, the program may create a deep copy of the input stream.
            // If the picture is decoded step by step, true will reduce the decoding speed of the picture. If the image in the path is not in a supported format, an exception will be thrown
            BitmapRegionDecoder decoder = BitmapRegionDecoder.newInstance(isBm, true);

            final int imgWidth = decoder.getWidth();
            final int imgHeight = decoder.getHeight();

            BitmapFactory.Options opts = new BitmapFactory.Options();

            //The image is divided into several pieces.
            // If sum=0 indicates that the length of the picture is less than 3000px, add it directly without segmentation.
            // If sum > 0, first add the whole graph, then add the extra parts, otherwise the bottom will be blank when the extra parts are less than 3000
            int sum = imgHeight/3000;

            int redundant = imgHeight%3000;

            List<Bitmap> bitmapList = new ArrayList<>();

            //Description picture length < 3000
            if (sum == 0){
                //Direct loading
                bitmapList.add(resource);
            }else {
                //Explain the need to segment pictures
                for (int i = 0; i < sum; i++) {
                    //Note: the fourth parameter of mRect.set(left, top, right, bottom).
                    //That is, the height of the picture cannot be greater than 4096 here.
                    mRect.set(0, i*3000, imgWidth, (i+1) * 3000);
                    Bitmap bm = decoder.decodeRegion(mRect, opts);
                    bitmapList.add(bm);
                }

                //Use the surplus part less than 3000 as the tail splicing
                if (redundant > 0){
                    mRect.set(0, sum*3000, imgWidth, imgHeight);
                    Bitmap bm = decoder.decodeRegion(mRect, opts);
                    bitmapList.add(bm);
                }

            }

            Bitmap bigbitmap = Bitmap.createBitmap(imgWidth, imgHeight, Bitmap.Config.ARGB_8888);
            Canvas bigcanvas = new Canvas(bigbitmap);

            Paint paint = new Paint();
            int iHeight = 0;

            //Take out the previous bitmap and splice it into a bitmap
            for (int i = 0; i < bitmapList.size(); i++) {
                Bitmap bmp = bitmapList.get(i);
                bigcanvas.drawBitmap(bmp, 0, iHeight, paint);
                iHeight += bmp.getHeight();

                bmp.recycle();
                bmp = null;
            }

            mImageView1.setImageBitmap(bigbitmap);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

Layout file

<ScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent">
            <ImageView
                android:id="@+id/iv_big"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:adjustViewBounds="true"
                android:scaleType="fitXY"/>
</ScrollView>

Note: the fourth parameter of mRect.set(left, top, right, bottom) cannot be greater than 4096. Finally, compress the image as much as possible.



By IOT XC
Links: https://www.jianshu.com/p/ef44310cfe72
Source: Jianshu
The copyright belongs to the author. For commercial reprint, please contact the author for authorization. For non-commercial reprint, please indicate the source.

Posted by Tezread on Tue, 29 Oct 2019 14:02:51 -0700