This is the second chapter of this series, together with the question about loading high-definition HD in Android, we all know that if we load the original image, one is very slow, need to wait a certain time, if not in a certain time to respond to the user, will greatly affect the user experience. The other is that if your phone's memory is small, it may crash directly. This is the problem of directly loading HD artwork. It is easy to think of these problems is the image compression, this article is to tell the picture compression method to achieve the effect of loading high-definition large image. But now the problem, through the previous blog we know that the resolution of a number of mobile phones, how to ensure that I have the same picture in different resolutions of the mobile phone can be properly compressed proportional display it??? Some people simply compress the dots, so they can be displayed on different phones with multiple resolutions. But we all know that the smaller the compression, the higher the distortion rate. It is easy to understand that most of the things we use are bitmaps, bitmaps have a feature is a lot of pixels of pixel matrix, when we compress the image is the equivalent of pixels, originally displayed this image needs 720*1280 pixels, now compressed into 320*480 pixels, Such a small number of pixels is not enough to show the original effect, the final result is clearly unclear image display. So finding a suitable compression ratio is especially important.
So how do we do it? The general idea of implementation is as follows: our so-called compression is actually to set a insamplesize (sample rate) attribute in the bitmap, through which the image compression can be achieved. How to set an appropriate value for the Insamplesize property?? First of all because the resolution of the screen is diversified, and then my picture will be based on different resolutions to get different insamplesize, so it is appropriate to display on my phone screen. So you need to get the height and width of the screen before you get to the screen height and width. Then use the width of the picture, the height of the screen to remove the height and width, and finally get the height ratio and width ratio.
Here there are two ways to achieve compression: one is cumbersome, the other is more straightforward.
First of all, say the first compression method.
Since most of the pictures are bitmap display, that is, the specific number of pixels to display, at different resolutions of the phone screen display picture white is in the total number of different pixels of the screen display, it is easy to understand, when I have a large picture, so-called very large picture is the total number of pixel points, And in the low-resolution (total pixel less display) there must be a problem, can only show the part, so you need to properly compress the size of the image according to the current phone resolution size, and then to display at the corresponding resolution of the screen when I get a picture in a way, there are several situations: Picture width (imwidth), picture height (imheight), screen width (width), screen height (height)
1, if the width of the picture is greater than the height of the picture (that is, horizontal picture), and wider than the screen width: size=imwidth/width
2, if the height of the picture is greater than the width of the picture (that is, portrait), and height is greater than screen height: size=imheight/height;
3, is according to a picture compression proportional algorithm formula: Take the picture width compression multiples and the picture height compression multiples average value: size= (imwidth/width+imheight/height)/2;
Finally, we assign the size we get in different cases to our insamplesize.
Then, say the second type, the second one is more direct violence, giving a formula directly:
INSAMPLESIZE=MATH.SQRT (widthscalesize*widthscalesize+heightscalesize*heightscalesize);
This formula is a bit like the mathematical Pythagorean theorem, but I think it makes sense, it takes such a insamplesize, in fact, similar to the diagonal compression ratio.
Finally, a way, this is called image quality compression, is in the process of compressing the picture, how to try to ensure the quality of our pictures?? Mainly through the bitmap of the compress to achieve
Compression of the Mass. Let's see how the source code is introduced.
/**
* Write A compressed version of the bitmap to the specified outputstream.
* If This returns true, the bitmap can is reconstructed by passing a
* Corresponding InputStream to Bitmapfactory.decodestream (). Note:not
* All Formats-bitmap configs directly, so it's possible that
* The returned bitmap from Bitmapfactory could is in a different bitdepth,
* and/or May has lost per-pixel alpha (e.g. JPEG only supports opaque
* pixels).
*
* @param format the format of the compressed image
* @param quality Hint to the compressor, 0-100. 0 meaning compress for
* Small size, meaning compress for max quality. Some
* formats, like PNG which is lossless, would ignore the
* Quality setting
* @param stream the OutputStream to write the compressed data.
* @return True if successfully compressed to the specified stream.
*/
Bitmap.compress (Bitmap.CompressFormat.PNG, BAOs)
It basically means that a bitmap object is saved in a certain output stream, and compress returns a Boolean value if it returns True
A Bitmap object is reconstructed by an input stream corresponding to it, and then annotated: not all formats support this way directly, which results in different size bitmap possible
Will lose the transparency of the original image pixel. Forces such as JPEG format images only support opaque pixels. Also need to note: Is inside the quality parameter introduction: It is said that the Quatily value range is: 0 to 100
0 represents the lowest quality, 100 represents the highest quality, if it is a PNG format picture, ignoring the quality value of the setting, it will cause distortion of the picture.
Then with the above understanding, I believe the following code is easier to understand.
Package Com.mikyou.loadbigimage;import Java.io.bytearrayinputstream;import Java.io.bytearrayoutputstream;import Java.io.ioexception;import Android.app.activity;import Android.graphics.bitmap;import Android.graphics.bitmapfactory;import Android.media.exifinterface;import Android.os.bundle;import Android.os.environment;import Android.util.displaymetrics;import Android.view.view;import Android.widget.imageview;public class Mainactivity extends Activity {private ImageView bigiv; private int Width, height, imwidth, imheight;//gets the height and width of the screen as well as the height and width of the picture @Override protected void onCreate (Bundle Savedin Stancestate) {super.oncreate (savedinstancestate); Setcontentview (R.layout.activity_main); Getscreenwidthandheight (); Bigiv = (ImageView) Findviewbyid (R.ID.BIG_IV); The public void Loadbigimage (view view) {//reads the status of the SD card and-determines if the SD card is available if (Environment.getexternalstoragestate () . Equals (environment.media_mounted)) {//To determine if the state of the SD card is available, the MNT directory shell--->emualted---->0//If it is available, read the path to the SD card and then load it out//if the picture is too large to cause the picture to load the delay may even cause the memory overflow, therefore needs to do the picture to be certain compression processing Bitmapfactory.options Options = new Bitmapfactory.options (); String path = environment.getexternalstoragedirectory () + "/img_big_1.jpg"; /** * Thinking: How to properly set up insamplesize to target different resolutions of the mobile phone, so as to get a better picture compression scheme?? * Analysis: * Since most of the images are bitmap display, that is, the specific number of pixels to display the picture at different resolutions of the phone screen * White is displayed in the screen of the total number of different pixels, it is easy to understand, when I have a big picture, so-called very big picture * is the total number of pixels, and in the low-resolution (total pixel less display) there must be a problem, can only show the part, so need * According to the current phone resolution size, to properly compress the size of the picture, and then to display the corresponding resolution of the screen * When I get a picture in a certain way, there are several things: * Picture width (imwidth), picture height (imheight), screen width (width), screen height (height) * One, according to the SD card path load picture size ratio compression * 1, if the width of the picture is greater than the height of the picture (that is, landscape), and the width is larger than the screen width: size=imwidth/width * 2, if the height of the picture is greater than the width of the picture (that is, portrait), and height is greater than screen height: size=imheight/height; * 3, is based on a picture compression ratio algorithm formula: Take the picture width compression multiplier and the image height of the compression multiplier average: size=(imwidth/width+imheight/height)/2; * Second, the image of the quality of compression * Three, according to bitmap to compress the picture size ratio * *///bitmap=getimagecompress (bitmap); bitmap= getimagebyscalesize (bitmap); Bitmap Bitmap=getimagebyscalesizebytec (path); Bigiv.setimagebitmap (bitmap); }}/** * Image quality Compression: * Image quality compression idea is as follows: * First to save a picture to a byte array output stream object, * and then by compressing the data until the image size is compressed to a specific size, and then the * The byte array output stream object is passed in as a byte array input stream parameter object to get a byte array input stream * Finally the byte array input stream gets the Bitmap object, finally gets the picture quality compressed picture */Public Bitmap getimagecompress (Bitmap Bitmap) {Bytearrayoutputstream BAOs = new Bytearrayoutputstream (); Bitmap.compress (Bitmap.CompressFormat.PNG, BAOs);//Quality compression method, where 100 means no compression, the compressed data is stored in the byte array output stream. int options = 100; while (Baos.tobytearray (). length/1024 > 100) {//cycle to determine if the picture is larger than 100kb after compression, greater than continue compression baos.reset ();//reset BAOs to Empty BA OS Options-= 10;//each time you reduce the bitmap.compress (Bitmap.CompressFormat.JPEG, OPtions, BAOs);//compress options% here, store the compressed data in BAOs} bytearrayinputstream ISBM = new Bytearrayinputstream (Baos.tob Ytearray ());//Store the compressed data BAOs in Bytearrayinputstream Bitmap bitmap2 = bitmapfactory.decodestream (ISBM, NULL, NULL);// Bytearrayinputstream data generation picture return BITMAP2; /** * Load picture size proportional to SD card path compression */public Bitmap getimagebyscalesize (String path) {int scalesize =1;//1 on table No compression bitmapfactory.options Options = new Bitmapfactory.options (); /* options.injustdecodebounds=true;//only reads the picture information, does not read the picture the specific data imwidth = Options.outwidth; Imheight = options.outheight;*/getimagewidthandheight (path);//Get the height and width of the picture if (Imwidth > Imheight &&am P Imwidth > Width) {scalesize = (int) (imwidth*1.0f/width+0.5f);//plus 0.5 is for rounding, take a good precision} else if (ImH Eight > Imwidth && imheight > Height) {scalesize = (int) (imheight*1.0f/height+0.5f); } else {//other cases, that is, when the picture is horizontal or vertical, its length andWidth is greater than screen scalesize = (int) (imwidth*1.0f/width + imheight*1.0f/height+0.5f)/2; }BA//Set the sample rate of the picture options.insamplesize = scalesize;//for different phone resolutions, set the zoom ratio is not the same, here the value may be different Bitmap BITMAP2 = Bitmapfactory.decodefile (path, options); return BITMAP2; }//Gets the height and width of the current phone screen private void Getscreenwidthandheight () {displaymetrics metrics = new Displaymetrics (); Getwindowmanager (). Getdefaultdisplay (). Getmetrics (metrics); Width = Metrics.widthpixels; Height = Metrics.heightpixels; }//Get the height and width of the original image private void Getimagewidthandheight (String path) {try {exifinterface Exifinterfe Ce=new exifinterface (path); Imwidth=exifinterfece.getattributeint (exifinterface.tag_image_width,0); Imheight=exifinterfece.getattributeint (exifinterface.tag_image_length,0); } catch (IOException e) {e.printstacktrace (); }}/** * Formula * */Public BitmapGetimagebyscalesizebytec (String path) {int scalesize =1;//1 means no compression getimagewidthandheight (path); int widthscalesize= (int) (imwidth*1.0f/width*1.0f+0.5f); int heightscalesize= (int) (imheight*1.0f/height*1.0f+0.5f); scalesize= (int) (MATH.SQRT (widthscalesize*widthscalesize+heightscalesize*heightscalesize) +0.5f); Bitmapfactory.options Options = new Bitmapfactory.options (); Set the sample rate of the picture options.insamplesize = scalesize;//for different phone resolutions, set the zoom ratio is not the same, here the value may be different Bitmap Bitmap = Bitmapfactor Y.decodefile (path, options); return bitmap; }}
Operation Result:
On Android loading HD large image and image compression method (ii)