Reprinted. Please specify href ="http://www.cnblogs.com/LuoYer/archive/2011/01/06/1929098.html"
target=
"_blank"
><em>http://www.cnblogs.com/LuoYer/archive/
2011
/
01
/
06
/
1929098
Declaration: I am referring to the code of 2.0, mainly referring to the bitmapfactory. Java file.
First, in the 2.0 application, there are three folders under Res to store images: drawable-hdpi, drawable-mdpi, and drawable-ldpi:
This is the difference in resolution, H is the high resolution M is medium L is low.
Differences between drawable-hdpi, drawable-mdpi, and drawable-ldpi:
(1) The drawable-hdpi contains high-resolution images, such as WVGA (480x800) and fwvga (480X854)
(2) drawable-mdpi stores medium-resolution images, such as hvga (320x480)
(3) drawable-ldpi stores low-resolution images, such as qvga (240x320)
I didn't quite understand it at first, so after reading the code, I first started an experiment, put the pictures in three folders respectively, and passed the following test code:
private int getTargetDensityByResource(Resources resources, int
id) { TypedValue value = new
TypedValue(); resources.openRawResource(id, value); Log.d( "LuoYer" , "value.density: "
+ value.density); return value.density; } |
Call the resources in the three folders, and print the resources as 240, 160, and 120 respectively.
Why? Let's take a look at the implementation of the decoderesource method we call in bitmapfactory. Java:
public static Bitmap decodeResource(Resources res,
int id, Options opts) { Bitmap bm = null ; InputStream is = null ;
try { final TypedValue value =
new TypedValue(); is = res.openRawResource(id, value); bm = <strong>decodeResourceStream</strong>(res, value, is, null , opts); } catch
(Exception e) { } finally
{ try {
if (is != null ) is.close();
} catch (IOException e) {}
} return bm; } |
Next, let's look at the decoderesourcestream method:
public static Bitmap decodeResourceStream(Resources res, TypedValue value, InputStream is, Rect pad, Options opts) { if (opts ==
null ) { opts = new
Options(); } if (opts.inDensity ==
0 && value !=
null ) { final int
density = value.density; if (density == TypedValue.DENSITY_DEFAULT) {
opts.inDensity = DisplayMetrics.DENSITY_DEFAULT; } else
if (density != TypedValue.DENSITY_NONE) {
opts.inDensity = density;
} } if (opts.inTargetDensity ==
0 && res !=
null ) {
opts.inTargetDensity = res.getDisplayMetrics().densityDpi; } return decodeStream(is, pad, opts); } |
The density value of value is used to determine the indensity setting of opts.
Therefore, when we obtain resources from three folders, the OPTs. indensity values are set to 240, 160, and 120, respectively.
The decoderesourcestream method sets opts. indensity and opts. intargetdensity. When its value is 0, it is assigned a value.
If you add log. D ("luoyer", "densitydpi:" + resources. getdisplaymetrics (). densitydpi) to the test function, a value of 160 will be printed on my board.
So, what is the relationship between opts indensity and intargetdensity for image resolution?
The decodestream method is used to call the finishdecode method (here only the computation diagram is listed. For details about the code, see bitmapfactory. Java). The computation that sets the scaling ratio when the returned image is created is as follows:
final int density = opts.inDensity; final int targetDensity = opts.inTargetDensity; float scale = targetDensity / (
float )density; |
The final scale is the scaling ratio, so if we put the image resourcesDrawable-hdpiOpts. indensity is 240,
When opts. intargetdensity is 0, it is set to 160. In this way, the returned image is scaled at a ratio of 2/3 (160/240.
InDrawable-mdpiThe image is not reduced.
Of course, this is also based on the value of resources. getdisplaymetrics (). densitydpi.
========================================================== ==============================================
The reason is clear. How can this problem be solved?
Put the image in drawable-mdpi. Of course, as I described earlier, this is acceptable. However, if the value of resources. getdisplaymetrics (). densitydpi changes, scaling occurs.
Since the final image creation uses scale, we only need to keep the density and targetdensity consistent to avoid scaling. Therefore, I encapsulated a parsing function:
private Bitmap decodeResource(Resources resources,
int id) { TypedValue value = new
TypedValue(); resources.openRawResource(id, value); BitmapFactory.Options opts = new
BitmapFactory.Options(); opts.inTargetDensity = value.density; return BitmapFactory.decodeResource(resources, id, opts); } |
In this way, no matter which folder the image is placed in, you do not have to worry about scaling.
1 |
<Em> I am not used to writing a blog for the first time. If you have any questions, please submit them in time for modification and improvement. For code details, see 2.0 Bitmapfactory. Java source code. </Em> |
1 |
For more information, see <a href = "http://www.cnblogs.com/LuoYer/archive/2011/01/06/1929098.html" target= "_blank" ><em>http://www.cnblogs.com/LuoYer/archive/ 2011 / 01 / 06 / 1929098 .html |