In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-04-12 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/03 Report--
This article mainly explains "what are the knowledge points of Bitmap". Friends who are interested may wish to have a look. The method introduced in this paper is simple, fast and practical. Now let the editor take you to learn "what are the knowledge points of Bitmap"?
What is Bitmap and how to store pictures.
Bitmap, a bitmap, is essentially a representation of the contents of a picture in memory. It regards the content of the picture as composed of a limited number of pixels that store data; each pixel stores the ARGB value of the pixel location, and the ARGB value of each pixel is determined, and the content of the picture is determined accordingly. Where A represents transparency and RGB represents the channel values of red, green and blue.
How to calculate Bitmap memory
Bitmap has always been a big memory user in Android, and there are three ways to calculate size:
GetRowBytes (), added in API Level 1, returns the size occupied by a row of bitmap. You need to multiply the height of bitmap to get the size of btimap.
GetByteCount (), which is added in API Level 12, is actually a high encapsulation of getRowBytes () multiplied by
GetAllocationByteCount () this was added in API Level 19
Here I put an image into the drawable-xxhdpi folder of the project, and then use the method to get the memory size of the image:
Var bitmap = BitmapFactory.decodeResource (resources, R.drawable.test) img.setImageBitmap (bitmap) Log.e (TAG, "dpi = ${resources.displayMetrics.densityDpi}") Log.e (TAG, "size = ${bitmap.allocationByteCount}")
The printed result is
Size=1960000
How exactly is it calculated?
Picture memory = width * height * bytes per pixel.
The number of bytes occupied by this pixel is also related to Bitmap.Config, which is an enumeration class that describes the information of each pixel, such as:
ARGB_8888 . Common types, a total of 32 bits, 4 bytes, representing transparency and RGB channels, respectively.
RGB_565 . 16-bit, 2-byte, can only describe the RGB channel.
So our picture memory calculation here shows:
Wide 700 * high 700 * 4 bytes per pixel = 1960000
The relationship between Bitmap memory and drawable directory
First, put a screen density comparison table corresponding to the drawable catalog, from Guo Lin's blog:
Comparison table
In the case just now, we put the pictures in the drawable-xxhdpi folder, and the dpi corresponding to the drawable-xxhdpi folder is the dpi-480 of the phone we tested. So the memory of the picture is the width * height * bytes per pixel we calculated.
What happens if we put the pictures in another folder, such as the drawable-hdpi folder (the corresponding dpi is 240)?
Print the results again:
Size = 7840000
This is because the formula for calculating the actual memory size of a picture is:
Occupied memory = wide * scale * High * scale * bytes per pixel
This zoom ratio is related to the screen density DPI:
Zoom = dpi of the directory where the device dpi/ picture is located
So the actual memory bit of our picture is:
Width 700x (480amp 240) * high 700K (480max 240C) * 4 bytes per pixel = 7840000
Bitmap load optimization? How to optimize without changing the quality of the picture?
There are two common optimization methods:
Modify Bitmap.Config
As mentioned earlier, different Conifg represents a different footprint for each pixel, so if we change the default ARGB_8888 to RGB_565, the footprint of each pixel will be changed from 4 bytes to 2 bytes, and the memory of the image will be halved.
It may reduce the quality of the picture to some extent, but I can't see any change in my actual test.
Modify inSampleSize
InSampleSize, sampling rate, this parameter is used for image size compression, it will be collected every inSampleSize pixels in the dimension of width and height, so as to achieve the effect of zooming the image. This method will only change the size of the picture and will not affect the quality of the picture.
Val options=BitmapFactory.Options () options.inSampleSize=2 val bitmap = BitmapFactory.decodeResource (resources, R.drawable.test2m options) img.setImageBitmap (bitmap)
In the actual project, we can set an inSampleSize that is similar to the size of the target image to reduce the actual memory used:
Fun getImage (): Bitmap {var options = BitmapFactory.Options () options.inJustDecodeBounds = true BitmapFactory.decodeResource (resources, R.drawable.test2, options) / / calculate the best sampling rate options.inSampleSize = getImageSampleSize (options.outWidth, options.outHeight) options.inJustDecodeBounds = false return BitmapFactory.decodeResource (resources, R.drawable.test2, options)} what is inJustDecodeBounds?
In the above example, you should find that there is an inJustDecodeBounds, which is set to true and false, and always feels superfluous, so what on earth is he doing?
Because we want to get the size of the image itself, if we load it directly with decodeResource, then the memory will be increased, so the official parameter inJustDecodeBounds is provided. If inJustDecodeBounds is ture, then the bitmap of decode is null, that is, the actual bitmap is not returned, only the size information of the image is put in the value of options.
So this parameter is used to get the size information of the image without taking up memory.
How to implement Bitmap memory reuse?
If there is a requirement that different images can be loaded in the same imageview, do we need to create a new Bitmap object each time, taking up new memory space? If we write like this:
Override fun onCreate (savedInstanceState: Bundle?) {super.onCreate (savedInstanceState) setContentView (R.layout.actvitiy_bitmap) btn1.setOnClickListener {img.setImageBitmap (getBitmap (R.drawable.test))} btn2.setOnClickListener {img.setImageBitmap (getBitmap (R.drawable.test2))}} fun getBitmap (resId: Int): Bitmap {var options = BitmapFactory.Options () return BitmapFactory.decodeResource (resources ResId, options)}
In this way, Bitmap will frequently apply for memory and release memory, resulting in a large number of GC, memory jitter.
To prevent this, we can use the inBitmap parameter for memory reuse of Bitmap. In this way, the same memory space can be reused by multiple Bitmap objects, thus reducing the frequency of GC.
Val options by lazy {BitmapFactory.Options ()} val reuseBitmap by lazy {options.inMutable = true BitmapFactory.decodeResource (resources, R.drawable.test, options)} fun getBitmap (resId: Int): Bitmap {options.inMutable = true options.inBitmap = reuseBitmap return BitmapFactory.decodeResource (resources, resId, options)}
Here are a few points to pay attention to
InBitmap should be used with the inMutable attribute, otherwise it will not be reused.
Prior to Android 4.4, only areas of Bitmap memory of the same size could be reused; after that, as long as the size of the Bitmap object that reuses the memory space is smaller than the memory space pointed to by inBitmap.
So generally before reuse, it is necessary to judge whether the new Bitmap memory is less than the reusable Bitmap memory before it can be reused.
How to deal with the loading of high-definition images?
If it is a high-definition large picture, it means that picture compression is not allowed, such as the long picture of Weibo and the picture of Riverside during the Qingming Festival.
So we have to partially display the picture, which uses the BitmapRegionDecoder attribute, which is mainly used to display a rectangular area of the picture.
For example, I want to display the 100 * 100 area in the upper left corner:
Fun setImagePart () {val inputStream: InputStream = assets.open ("test.jpg") val bitmapRegionDecoder: BitmapRegionDecoder = BitmapRegionDecoder.newInstance (inputStream, false) val options = BitmapFactory.Options () val bitmap = bitmapRegionDecoder.decodeRegion (Rect (0,0,100,100), options) image.setImageBitmap (bitmap)}
In the actual project use, we can slide according to the gesture, and then constantly update our Rect parameters to achieve specific functions.
For more information, please refer to Hongyang's blog: https://blog.csdn.net/lmj623565791/article/details/49300989.
How to pass large images across processes?
Bundle is passed directly. Bundle is most commonly used for inter-Activity transfer, and is also a cross-process way, but the size of the transfer is limited, generally 1m.
/ / the putExtra method of intent.put is also essentially through bundleintent.putExtra ("image", bitmap); bundle.putParcelable ("image", bitmap)
Bitmap can be passed directly because it implements the Parcelable interface for serialization. The transmission principle of Parcelable is to use the Binder mechanism to write the Parcel serialized data into a shared memory (buffer). When reading, it will also read the byte stream from this buffer, and then deserialize it into an object. This shared memory, or cache, has a size limit of 1m and is common. So if you send a picture, it's easy to exceed this size and report the wrong TransactionTooLargeException.
So this plan is unreliable.
File transfer.
It is certainly possible to save the picture to a file and then transfer only the file path, but it is not efficient.
PutBinder
This is the test site. Pass binder by passing bitmap.
/ / pass binderval bundle = Bundle () bundle.putBinder ("bitmap", BitmapBinder (mBitmap)) / / receive bitmapval imageBinder in binder: BitmapBinder = bundle.getBinder ("bitmap") as BitmapBinderval bitmap: Bitmap? = imageBinder.getBitmap () / / Binder subclass class BitmapBinder: Binder () {private var bitmap: Bitmap? = null fun ImageBinder (bitmap: Bitmap?) {this.bitmap = bitmap} fun getBitmap (): Bitmap? {return bitmap}}
Why is there no size limit for using putBinder?
Because what is passed in putBinder is actually a file descriptor fd, the file itself is put into a shared memory, and then after getting the fd, you only need to pull the Bitmap data from the shared memory, so the transfer is very efficient.
When transferring directly with Intent/bundle, the file descriptor fd is disabled, and only space can be allocated in the cache area of parcel to save data, so the size limit of 1m cannot be broken.
The file descriptor is a simple integer that identifies each file and socket opened by the process. The first open file is 0, the second is 1, and so on.
At this point, I believe you have a deeper understanding of "what are the knowledge points of Bitmap?" you might as well do it in practice. Here is the website, more related content can enter the relevant channels to inquire, follow us, continue to learn!
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.