Android Select local image and about image compression upload problem

Source: Internet
Author: User

<span style= "FONT-SIZE:18PX;" > In a project, there is a need to let users choose their own pictures, and then upload to the server. Seemingly a very simple need, is to choose the picture, the picture installed, and then through the network request upload to the background, OK. But this is not the case, because we can Android project, he is open, he has more possibilities, of course you will also encounter more extravagant the problem. </span>

There are 3 ways to get pictures, one is to use the surface control, using the lens to obtain the picture, and the second is to call the system camera, and return the pictures taken; third, directly in the use of the library to obtain local images; Here I only use the following two methods to get the picture (the system provides a method, why not? It will take so much effort to develop a new function that has already been made, not to reinvent the wheel. In the process, I met several wonderful and incomprehensible questions. Got me a half a day, now make a record.

Some of the problems I have encountered are as follows:

1, the use of system map to obtain images, the return of the image address, due to different systems and different;

2, the use of photographs returned photos are compressed, the resolution is very low, at all not clear;

3.

First question: The address of the image returned is different. Why, because we know that Android has a lot of deep custom systems like Xiaomi, Huawei, Meizu, hammer ... And so on, the original Android system has been modified to optimize, at least I do not know what they can change at the bottom of something, we have to face the bottom of the return, to adapt to it. Here, we use the display intent way to open this map library, the code is as follows

Intent Intent = new Intent (intent.action_get_content, NULL);//Set action

<span style= "FONT-SIZE:18PX;" ><span style= "White-space:pre" ></span>intent.settype ("image/*");//Open Pictures screen type set to image< Span style= "White-space:pre" ></span>startactivityforresult (Intent, Capture_image_activity_request_code1 );</span>
This allows you to open the system's gallery to select the desired image.

So, here's the problem. I opened in the Blue 2, the system jumps to the most recent photo shoot, and on the Xiaomi 2s above is also jump to the latest shot of the collection of pictures inside, Huawei Honor6? It jumps to the recently edited picture collection. Finally, in the Onactivityresult () callback method, use the following code to get the image address:

<span style= "FONT-SIZE:18PX;" ><span style= "White-space:pre" ></span>uri Uri = Data.getdata ();        String pathimg = Uri.getpath ();</span>
Glamour Blue gets to 2 the path to the picture is:/external/images/media/640543, Xiaomi 2s is:/storage/sdcard0/dcim/camera/ Img_20160217_142658.jpg, Huawei's similar charm Blue 2 path, here is not printed out. Here I want to select the full path of the picture, if you do not need the full path, but also can get to the picture, the code is as follows:

Bitmap Bitmap = bitmapfactory. Decodestream (Contentresolver.openinputstream (URI)); This method returns is a bitmap, a see bitmap should immediately think of is oom, this is a program ape and love and hate things ah. Now the phone casually take a picture, there are 1000 (+) *1000 (+) pixels, in the android inside a pixel, with 4 bytes stored. So, read into a 1000*1000 pixel picture, read in, the number of bytes occupied has 1000*1000*4. This is almost deadly for a program. Such an approach is obviously undesirable.
In the path returned above, Xiaomi 2s returns the right path, but my code is still running on the Phantom Blue, and obviously it's not going to pass. So I found another way to get back the picture path:
String PicturePath = "";        String[] proj = {MediaStore.Images.Media.DATA};        cursor cursor = getcontentresolver (). Query (URI, proj, NULL, NULL, NULL);        if (cursor! = NULL && Cursor.movetofirst ()) {            int columnindex = Cursor.getcolumnindex (proj[0]);            PicturePath = cursor.getstring (columnindex);            System.out.println ("-=-==->>picturepath =" + PicturePath);        }
This method, in Huawei Honor6? The cursor returned above is NULL, the charm is OK on the blue, and the millet is null. This makes people very puzzled. It's also a way to show the system, but it's a different thing to return. And my goal is to either oom and complete the path.
So here, I used a wretched way to get around this hole. That is, I use two methods to get two paths, and then determine which path is not NULL, and the path with the picture format suffix is used.
The use of this is to compress the image and then read the compressed image into memory. Here's My method:
</pre>


/** * According to the picture path, Get compressed Bitmap * * @param path * @param width * @param height * @return */public Bitmap GETPRESSEDBI TMap (String path, int width, int height) {bitmapfactory.options Options = new Bitmapfactory.options ();//new a Optio NS Options.injustdecodebounds = true;//First set to true, that is, do not read into the image to memory, first obtain the information of the picture, such as the length and width of information Bitmap Bitmap = Bitmapfactory.dec Odefile (path, options);//This code is really to read the image of the length and width of information, and stored in the options, in the following code we can see Options.outwidth and What Options.outheight get is the width and height of the picture. This code so cannot not, otherwise cannot compress the picture. The bitmap obtained here is null options.insamplesize = Getbitmapsamplesize (options, width, height), or the proportion of the picture compressed according to the given width of the height optio Ns.injustdecodebounds = false;//is set to False to compress the picture into memory after a certain proportion of the   is read; 
<span Style= "White-space:pre" ></span>bitmap bitmap1 = bitmapfactory.decodefile (path, options);//   The bitmap obtained here is not a null return BITMAP1;}   
<pre name= "code" class= "java" >/**     * According to the width to go, compress the picture     *     * @param options     * @param reqwidth     * @ Param reqheight     * @return * * * public    int getbitmapsamplesize (bitmapfactory.options Options, int reqwidth, int reqheight) {        int imgwidth = options.outwidth;        int imgheight = options.outheight;        int insimplesize = 1;        if (ImgWidth > ImgHeight | | imgwidth < imgheight) {            final int heightratio = imgwidth/reqwidth;            Final int widthRatio = imgheight/reqheight;            Insimplesize = WidthRatio < HeightRatio? Widthratio:heightratio;        }        return insimplesize;    }


Finally, I will choose a good picture, upload to the background, found that the image of the pixel is very low, almost do not see what is uploaded, this is not in line with the demand. So to modify.
  I send Now put options     insamplesize   =  5    //getbitmapsamplesize (options, width, height) change to such a child,      insamplesize change to an int that you think you can see clearly is OK. (Here's a reminder, also note that the size of the bitmap is read in,      The  picture is not too large,       because the upload is a traffic-intensive, we must stand on the user's point of view to think about the problem)   
Finally, the problem is actually solved, but theoretically have not, can't think of, how can I also have no time to one by one to see the source. Wait for an empty time, then go to the source code.
For the second question: photos returned with pictures are compressed, the resolution is very low, at all unclear. We use the explicit intent to open the system camera, and then return the picture information, the code is as follows:
bundle = Data.getextras (); Bitmap Bitmap = (Bitmap) bundle.get ("Data");//Get the data returned by the camera and convert it to Bitmap picture format
As you can see, the image data returned from the call to the system camera is placed inside the bundle. I will bitmap out, found that the pixel is also low enough, there is no way to see, the original returned is not a compressed image. Of course it's not. The picture you found is not stored locally, and you cannot reuse that picture.
In this case, I will check the information, thinking that the system should have a way to set up to return the original image, but I have not found. And then see another way, first take the photo of the location of the specified position, and then use the specified location to obtain the original image, compressed, after reading in.
The first time you start calling the system camera, specify the location of the photo storage.
Take advantage of the system's own camera application: Photo        Intent Intent = new Intent (mediastore.action_image_capture); File FilePath = Gettakephotopath ();//Get picture file stored path Uri Imguri = Null;imguri = Uri.fromfile (filePath); Cacheimgpath = Filepath.getabsolutepath ();//The path of the picture is saved Intent.putextra (Mediastore.extra_output, Imguri);//Pass the path to the system, The system is automatically saved to the path you specify GetParent (). Startactivityforresult (Intent, CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE2);
/** * Returns a storage path for taking pictures * * @return path */private File Gettakephotopath () {SimpleDateFormat format        = new SimpleDateFormat ("Yyyymmddhhmmss");        Date date = new Date (System.currenttimemillis ());        String fileName = Format.format (date);        File File = environment.getexternalstoragepublicdirectory (ENVIRONMENT.DIRECTORY_DCIM);        String Imgpath = File.getabsolutepath () + "/test/";        File Filedcim = new file (Imgpath);        if (!filedcim.exists ()) {filedcim.mkdirs ();        } File Filepicpath = new file (FILEDCIM, "sbd_" + fileName + ". jpg");            if (!filepicpath.exists ()) {try {filepicpath.createnewfile ();            } catch (IOException e) {e.printstacktrace ();        }} String Path = Filepicpath.getabsolutepath ();        if (path = = null) {return null;        } else {return filepicpath; }    }
In the Onactivityresult () callback, use the saved path to get a compressed image of the local image as shown above OK.
Of course, when doing this, don't forget to add the appropriate permissions.
These are my personal views on this issue and solutions, if found something wrong, or there is a better way to solve the problem, please enlighten!


Android Select local image and about image compression upload problem

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.