Android Bitmap Open Source image framework analysis (Essence five)

Source: Internet
Author: User

This post was last edited by Boredream on 2014-5-27 09:07

Imageloader and volley pictures also include most of the other picture frames, the basic chip processing is similar, the difference is only part of the optimization, and the optimization of UIL that is universal-image-loader framework to do the best, So this part of the chapter is to review a piece of processing and look for some of the other frames in the different image processing methods (only focus on the picture)




First, Imageloader.
Https://github.com/novoda/ImageLoader
The main part is to analyze the core code of image loading, other places briefly introduce

Zoom problem for single picture
The core method is as follows ~
Int calculatescale (final int requiredsize, int widthtmp, int heighttmp) {     int scale = 1;    while  (true) {        if& nbsp (WIDTHTMP/2) < Requiredsize | | (HEIGHTTMP/2) < requiredsize) {            break;      & nbsp; }        widthtmp/= 2;        heighttmp/= 2;& nbsp       scale *= 2;   }    return scale;} It is also written in a change, in fact, the meaning of the UIL framework in the crop type of scaling, but also the same as the official recommended basic processing (see tutorial I) as follows while  (SRCWIDTH/2 >= targetwidth && SRCHEIGHT/2 >= targetheight) { //&&     srcwidth/= 2;      Srcheight/= 2;     scale *= 2;} Identical ~!~!~!~! Two conditions completely in turn, while one is the condition of the while continuation, one is the condition of break interruption, so the combination of the actual meaning is exactly the same as the Imageloader frame is equivalent to the one in our tutorial, only a case of parsing, no UIL kind ofThe difference between the same scaling method   also is the color style modification framework source code Global search for the next key word, also found the home page document introduction, seemingly did not find imageloader on the color sample has set, need to modify the color sample words need to achieve their own   Cache Pool Section Imageloader framework three cache pools lrubitmapcache  strong reference cache for &NBSP;&NBSP;&NBSP;LRU algorithm nocache                   No caching (in fact, it doesn't count as a cache pool, it doesn't make sense to use this class) softmapcache          Soft Reference cache   supported types are few, the cache pool can only be counted two, using strong references alone and using soft references alone, there is no level two cache processing also provides three types, the user set the cache type, Set method to Settingsbuilder.withcachemanager (...) Analysis of  lrubitmapcache Strong reference cache
In the framework of customizing a LRUCache class, not the official LRUCache class, but the implementation logic is similar (basically the same), i contrast, is equivalent to the official LRUCache Class +uil Framework strong reference class of the complex ~
The internal implementation is also a linkedhashmap, the key method name is put and TrimToSize (originally also want to spit groove Why and UIL frame name--, the last discovery are imitate the official website LRUCache class method from the name), There is also a entryremoved method, but also directly imitate the official LRUCache write a method, meaning is more than the strong reference cache pool threshold, remove the oldest of the objects, you can replicate this method, the removal of the object to do the necessary processing (such as moving it to the soft reference cache, Implement a level two cache yourself) Public final v put (K key, V value) {    if  (Key == null | | Value == null) {        throw new nullpointerexception (  "key = = null | | Value = = null  );   }    V previous;    synchronized  ( this) {        putCount++;        size += safesizeof (key, value) ;        previous = map.put (key, value);        if   (previous!= null) {            size -= safesizeof (Key, Previous);        }   }     if  (previous!= null) {        entryremoved ( false, key, Previous, value);  & nbsp }     TrimToSize (maxSize);    return previous;}   A simple nagging. Putcount record add quantity, here temporarily not to introduce synchronized is to ensure multithreading access when size calculation includes Putcount calculation do not appear chaotic first size + = Add the size of the put object to the current cache pool size The return value of Map.put is the value of the replacement value returned for key, if non-null means that the last is removed, naturally to-= minus its size value, and then the key entryremoved method, The inside of the method is no content, just the equivalent of removing the bitmap object as a parameter passed in the method last called the TrimToSize method to detect whether the current cache size is greater than the threshold, do the corresponding processing  private void  TrimToSize (int maxsize) {    while  (True) {        k key =  null;        v value = null;         synchronized  ( this) {            if  ( size < 0 | | ( map.isempty () && size != 0)) {                throw new ilLegalstateexception (GetClass (). GetName () +  ". SizeOf () is reporting inconsistent results!"  );            }             if  ( size <= maxSize) {                 break;            }            / /change             if  ( map.entryset (). iterator (). Hasnext ( )) {                map.entry<k, v> toevict = map.entryset ( ). iterator (). Next ();                if  (toevict ==  NULL) {                    break;   & nbsp           }         &NBsp;       key = Toevict.getkey ();                VA Lue = Toevict.getvalue ();                map.remove (key);                 size -= safesizeof (key, value);                evictionCount++;            }        }         entryremoved ( true, Key, Value, null);   } and the UIL framework are similar (in fact, the official LRUCache class for the method change, so the name logic almost no difference) Detects if size is more than maxsize, removes it, and then  entryremoved method for size processing
Internal is empty, parameters to do a simple introduction, is mainly the first Boolean parameter, you can directly refer to the source code in Linkedhashmap similar method
This means that true is to remove objects that are guaranteed to be removed by the object, while false is the object that is removed when the put substitution and remove are common.
So if you want to implement a level two cache in this framework, you can customize the LRUCache class of the subclass replication Imageloader Framework, and then replicate this class,
Inside, if the first argument is true, save it to a soft application/weak reference level two cache pool




Softmapcache Soft Reference Cache
There is only one soft reference, no quantity control so there's nothing to analyze, just a simple map<string, softreference<bitmap>> cache type Collection
Then provide basic methods such as put remove




In general, the most basic of all, but not perfect, you need to implement some enhancements such as level two cache
Now almost all use UIL frame, so imageloader basic only provide a small reference, if want to study the source and feel uil more complex, can see Imageloader, in the project use, or recommend UIL, I ~ believe the masses ~


---------------------------------------------------------------------------


Volley Frame Picture Loading section
Unlike the previous two frames are focused on image loading, this framework is comprehensive, and the main advantage is the network data asynchronous request part, and the picture loading part is not very complete, only provide the most basic processing, the following analysis


First, the processing of a single image
Similarly, a global search for the keyword Insamplesize a way to navigate to the Imagerequest class
/*** the real guts of parsenetworkresponse. Broken out for readability.*/private response<bitmap> Doparse (networkresponse Response) {     byte[] data = response. data;    bitmapfactory.options decodeoptions = new  Bitmapfactory.options ();    Bitmap Bitmap = null;    if  (mmaxwidth == 0 & & mmaxheight == 0) {        decodeoptions. inpreferredconfig  = mDecodeConfig;        bitmap = Bitmapfactory. decodebytearray (data , 0, Data.length, decodeoptions);   } else {        //If We have a to re Size This image, first get the natural bounds.        decodeOptions.  injustdecodebounds = true;        bitmapfactory. decodebytearray ( Data, 0, Data.length, decodeoptions);     &nbsP;  int actualwidth = decodeoptions. outwidth;        int  ActualHeight = decodeoptions. outheight;         //then compute the Dimensions we would ideally like to decode to.        int desiredwidth =  Getresizeddimension (mmaxwidth , mmaxheight ,                 ActualWidth, actualHeight);        int desiredheight =  Getresizeddimension (mmaxheight , mmaxwidth ,                 ActualHeight, actualwidth);         //Decode to the nearest power of Scaling factor.        decodeOptions. inJustDecodeBounds = false;         // TODO  (Ficus): Do we need this or is it okay sinceAPI 8 doesn ' t support it?        //decodeoptions.inpreferqualityoverspeed = Prefer_ quality_over_speed;        decodeOptions. inSampleSize =             findbestsamplesize (ActualWidth, ActualHeight, Desiredwidth, desiredheight);         bitmap tempbitmap =             Bitmapfactory. decodebytearray (data, 0, Data.length, decodeoptions);          //If necessary, scale down to the maximal acceptable size.        if  (Tempbitma P!= null && (Tempbitmap.getwidth () > Desiredwidth | |                 tempbitmap.getheight () > Desiredheight)) {  & nbsp;         bitmap = Bitmap. createscaledbitmap (tempbitmap,     & nbsp;             desiredwidth, desiredheight, true);             tempbitmap.recycle ();        } else  {            bitmap = tempbitmap;        }   }     if  (bitmap == null) {        return  Response.error (New parseerror (Response));   } else {         return response.success (Bitmap, Httpheaderparser.parsecacheheaders (Response));   } Two places are the key, One is getresizeddimension, the other is findbestsamplesize, respectively.


First look at the next findbestsamplesize, we are more familiar with the logical method as follows
    static int findBestSampleSize  (            int actualWidth, int actualHeight, int desiredWidth, int  Desiredheight) {        double wr = (double) actualwidth/desiredwidth;        double hr = (double) actualheight/desiredheight;         double ratio = Math.min (WR, HR);        float n = 1.0f;         while  ((n * 2) <= ratio) {            n *= 2;&nbs P       }         return  (int) n;   } Another algorithm ~ But the actual meaning is the same as in the tutorial-the mathematical logic should be able to see, can not see the ... To do a demo comparison of the results of several methods of different values, too lazy to test, then believe me, the basic is the difference between the specific calculation efficiency of the difference between my level is not studied, but this kind of writing looks like it seems to be a bit of a drawback? You can use ~  when you want to write the image compression value calculation Then is another method of introduction getresizeddimension, have not seen before, a little reference value ~
Get the resized size, that is, to get the desired compressed image size value of a calculation method, the processing method is very special, you can skip, in fact, different through this method to "adjust", directly using the custom MaxWidth maxheight limit the width of high value on the line, The following section is a simple analysis of this method, with limited energy to skip ~


-----------------------------------------------------------------------------------


Originally want to lazy online Search This method of explanation, unfortunately most found a sentence "according to certain rules calculated ...", Forget I run the project side merely bar ~ Actually this method of learning reference value a little more, actually set the required compression width high value, the picture will follow the same rule to get a proper value , that is, not using the method of compression effect is also possible
    /**     * Scales one side of a rectangle to fit aspect ratio.  &NBSP;&NBSP;&NB sp;*     *  @param  maxprimary Maximum size of the primary dimension (i.e. width for  &n bsp;  *        max width), or zero to maintain aspect ratio with secondary  & nbsp;  *        dimension     *  @param   Maxsecondary Maximum size of the secondary dimension, or zero to     *         maintain aspect ratio with primary dimension     *  @param  actualprimary Actual Size of the primary dimension     *  @param  actualsecondary Actual Size of the secondary dim ension     */    private static int getResizedDimension  ( Int maxprimary, int maxsecondary, intactualprimary,            int actualsecondary) {        //If No dominant value at all, just return the actual.        if  (ma Xprimary = = 0 && maxsecondary = 0) {            return actualprimar y;        }         //If Primary is unspecified, Scale primary to match secondary ' s scaling ratio.        if  (maxprimary = = 0) {  & nbsp;         double ratio = ( double) maxsecondary/( double) actualsecondary;            return  ( int) (Actualprimary * ratio), & nbsp       }         if  (maxsecondary = = 0) {            return maxprimary;        }         double ratio = (  Double) actualsecondary/( double) actualprimary;        int resized = maxprimary;        if  (resized * ratio > maxsecondary) {            resized = ( int) (maxsecondary/ratio);        }& nbsp The       return resized;   } method passes 4 data, i.e. two sets of
A group is Max, which is the limit value, divided into two primary and secondary values, not the meaning of width, the main value is likely to be the width of the secondary value is high, it is possible to be high-primary value, the width of the secondary value
The other group is the actual value of the actual, that is, the image's original width high value, also divided into primary and secondary, Max Master is the limit height, the second is the limit width, the actual value is high for the main, the second is wide, and vice versa
--meaning unclear?


Using the method is called two times, the main is the height of the width, the result of the calculation is adjusted to the desired height value, that is, the calculation of the main required value
Similarly, when the master is wide, the calculated result is the adjusted desired width value
--meaning or unclear? Let's keep looking.


Give me a practical example.
If you set a qualified wide-height value, such as MaxWidth = MaxHeight = 200, the original picture is loaded on my side is an image of width * height is the figure of 720*617
Call two methods to get the desired value, respectively
int desiredwidth = getresizeddimension (180, 200, 720, 617); Gets the desired width value after adjustment
int desiredheight = Getresizeddimension (200,180, 617,720); Gets the adjusted desired height value calculation result desiredwidth = 180;desiredheight = 154;  Intuitively, the desired width and height are adjusted to the same proportions as the original width (the desired width and height adjustment ratio 180/154≈1.17     original ratio 720/617≈1.17)   test again, the same picture, MaxWidth and MaxHeight are set to 200, the result is desiredwidth = 200;desiredheight = 171. The aspect ratio is the same as the original (200/171≈1.17)   that is, when the limit width height is set (neither 0), calculate the original proportion and then adjust the width height to the same proportion as the original image. And the adjusted width and height value is less than or equal to the original limit of the width of either side is 0 or 0 of the case here does not analyze, is not too important, is the limit value of 0 is not set the value of a corresponding processing    before the UIL frame for two different scaling types, The compression scale value calculation is differentiated into two types, one is | | Connection conditions, one is the && connection condition | | The processing result is to ensure that any one edge of the image after compression is greater than the limit of the corresponding edge can be && processing result is to ensure that the image width and height two edges are greater than the limit value of the corresponding edge  && processing and the official provided examples of the same, Also introduced in tutorial one of the calculation method that volley of this algorithm, a simple experiment with a few data, I found the results and UIL in the fit_inside situation that is | | The results of the connection condition calculation almost, I also have a simple demo comparison of the results of the two groups of different data, are also consistent ~ logical understanding, if the limit value and the original proportion of different, then the processing of the limit value of one side will be reduced ~ that with this adjusted limit value compressed image, The final result is possible: the last acquired compressed picture style one edge is less than the limit value we set before the corresponding edge result in the case that only one edge satisfies a value greater than or equal to the limit, that is, the same as the Fit_inside case in UIL    summary, The official method is to ensure that no matter what the zoom display type, can guarantee that the picture width high value is greater than or equal to the limit value UIL better, different circumstances are considered, the proportion of the calculation of the comparison of the precise volley frame is another, that is, by default, can guarantee the image sharpness (pixel density can achieve the target), However, the size of the crop and other scaling types, especially the large length and width situation, there is no guarantee of sharpness when the picture is compressed (because of this less, the compression quality is guaranteed in most cases) Note: There may be inaccuracies in the place I'm tidying up 1. Tutorial One official method 2.UIL frame 3.Volley frame picture processing the specific data comparison of three, Because the amount of data is large and miscellaneous, so after such as ~ fruit ~ can be organized smoothly and have time, just open a chapter on the framework to do a simple comparison ~ ---------------------------------------------------------- -----------------   Color Styles Section
Frame source is the image color style set to rgb_565, is also directly written dead   multiple pictures cache Pool A wood has--only provides a cache pool type interface Imagecache, need to customize the class to implement its online mainstream practice, Including the demo is to customize a class to inherit LRUCache and then implement volley framework in the corresponding interface class notation is also very simple, tutorial two familiar words estimate will write, class code is as follows public class bitmaplrucache  Extends lrucache<string, Bitmap> implements imagecache {    public  Bitmaplrucache ( int maxsize) {        super (maxSize);   }       @Override     protected int sizeof (String key, Bitmap value) {        return value.getrowbytes () * Value.getheight ();   }      @Override     public bitmap getbitmap (String url) {         return get (URL);   }      @Override     public void  putbitmap (String URL, Bitmap Bitmap) {        put (URL, Bitmap);   }} again, You can also use linkEdhashmap implementation, you can also add a level two cache structure can be   ---------------------------------------------------------------------- -----


Simply over the Imageloader frame and the volley frame picture section, again from the side to verify the method of our tutorials
Also simple to these two frameworks have some understanding, if interested can find a few more well-known framework of their own look at the source code, estimating the difference is only in the Optimization section, the core logic is the same
Volley framework, compared to other frameworks, the function is actually very weak, only the most basic processing logic, even the cache pool needs a custom class implementation, but this is also an advantage, because volley is a comprehensive framework, has provided a good foundation, the network data part without us to consider too much, If you want to do a frame of their own, and do not want to write a little bit of their own, that volley is your best choice, we can do the framework of two times according to the need to develop ~ This is also my special volley out of the reasons for the introduction, then a chapter will be a few frames of different picture processing effect to make a simple comparison, Then one chapter is the volley frame picture cache two times development, I also first time, certainly has the insufficient place, when everybody together explores ~

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.