andorid-How to scale a picture for your Android app

Source: Internet
Author: User

Is it difficult to get the correct image scaling for your application? Is your picture too large to cause memory problems? Or is the picture improperly scaled resulting in a bad user experience? To find a good solution, we consulted Andreas Agvard (Sony Ericsson Software) to share some of his experience in this area.

Note: The code example is not fully displayed in this article. You can download the PDF of this article to see the complete code example.

Working in the Sony Ericsson Software Department, I often encounter applications that require image scaling, such as when working with other people or images that are available on the web. Scaling is necessary because the usual picture is not what you want to present.

A typical example if you are developing a liveview™ extension for your application. Most people who develop applications that utilize liveview™ and other second-screen devices may need to readjust the picture, and it is important to maintain proper scaling and image quality. Of course, in many cases, changing the size of a picture is a bit difficult, but a very effective way.

ImageView solves a lot of picture scaling problems, first of all, at least after you set up an image source, you do not have to decode or zoom the picture. But sometimes you need to decode your own control, which is where this tutorial comes in. With this tutorial, I wrote a code example to download the image scaling code sample. The effects that are rendered in the text can be seen by compiling and running the project.

Isolate the problem
I do this tutorial because I have some practical ways to achieve the zoom of the picture, in order to avoid the most common picture scaling problem. As in the following example:

Bitmap Unscaledbitmap == Bitmap.createscaledbitmap (Unscaledbitmap, Wantedwidth, Wantedheight,

So what's the right thing in the code above, and what's wrong? Let's take a look at the different lines of code.

Line 1: The entire source image is decoded to a bitmap.

    • This may cause an out-of- memory error if the picture is too large.
    • This may cause the image to be decoded at a high resolution. This can be slow , but the smart decoder can improve performance for decoding.
    • Zooming a picture many times, high-resolution bitmaps are scaled to a low resolution, which can cause aliasing problems. Use bitmap filtering (for example, by passing the ' true ' parameter to Bitmap.createscaledbitmap (...) ) reduces aliasing, but it's not enough.

Line 2: The decoded bitmap zooms to the desired size.

    • The size of the source image and the desired image size may be different on the aspect ratio. This causes the image to be stretched .

Picture on the left: original image. Picture on the right: scaled image. You can see the obvious distortion problem, such as the original eye is very sharp, after zooming out. The height appears stretched.

Create a solution
Our solution will have a structure similar to the above code, some of which will replace line 1, so as to prepare for scaling. The other part will replace Line 2 and do the final zoom. We will begin replacing part of line 2 with the code, introducing two new concepts, cropping and fitting .

Replace line 2
In this section, we will scale the bitmap to what we need. This step is necessary because the previous decoding capability is limited. Also, in order to avoid stretching in this step, we may want to resize the picture to the desired size.

There are two possibilities to avoid stretching. Either way, we have to adjust the dimensions to make sure they have the same aspect ratio, which is to scale the image as the source image until it fits the desired size, or to crop the source image with the same aspect ratio as the desired size.

Picture on the left: the image is scaled by the Fit method. The picture has been scaled down to fit the size and height, and the result is less than the desired height. Image on the right: image crop method scaling. The image has been scaled to fit at least the desired size. So the original image has been cropped and cut to the left and to the right two parts.

To scale such an effect, our implementation code is as follows:

 Public StaticBitmap Createscaledbitmap (Bitmap unscaledbitmap,intDstwidth,intdstheight, Scalinglogic scalinglogic) {Rect srcrect=Calculatesrcrect (Unscaledbitmap.getwidth (), Unscaledbitmap.getheight (), Dstwidth, Dstheight, scalingLogic); Rect Dstrect=Calculatedstrect (Unscaledbitmap.getwidth (), Unscaledbitmap.getheight (), Dstwidth, Dstheight, scalingLogic); Bitmap Scaledbitmap=Bitmap.createbitmap (Dstrect.width (), Dstrect.height (), config.argb_8888); Canvas Canvas=NewCanvas (SCALEDBITMAP); Canvas.drawbitmap (Unscaledbitmap, Srcrect, Dstrect,NewPaint (Paint.filter_bitmap_flag));returnScaledbitmap; }

In the above code, we use Canvas.drawbitmap (...) Do the scaling. The clipping area of this method is a rectangular region of the specified target rectangle that defines the canvas's rectangle from the size area of the source image. To avoid stretching, the two rectangles need to have the same aspect ratio. We also called two useful methods, one for creating the source rectangle and the other for creating the destination rectangle. Here's how:

 Public StaticRect Calculatesrcrect (intSrcwidth,intSrcheight,intDstwidth,intdstheight, Scalinglogic scalinglogic) {  if(Scalinglogic = =scalinglogic.crop) {Final floatSrcaspect = (float) Srcwidth/(float) Srcheight; Final floatDstaspect = (float) Dstwidth/(float) Dstheight; if(Srcaspect >dstaspect) {      Final intSrcrectwidth = (int) (Srcheight *dstaspect); Final intSrcrectleft = (srcwidth-srcrectwidth)/2; return NewRect (srcrectleft, 0, Srcrectleft +srcrectwidth, srcheight); } Else {      Final intSrcrectheight = (int) (Srcwidth/dstaspect); Final intScrrecttop = (int) (Srcheight-srcrectheight)/2; return NewRect (0, Scrrecttop, srcwidth, Scrrecttop +srcrectheight); }  } Else {    return NewRect (0, 0, Srcwidth, srcheight); }} Public StaticRect Calculatedstrect (intSrcwidth,intSrcheight,intDstwidth,intdstheight, Scalinglogic scalinglogic) {  if(Scalinglogic = =scalinglogic.fit) {Final floatSrcaspect = (float) Srcwidth/(float) Srcheight; Final floatDstaspect = (float) Dstwidth/(float) Dstheight; if(Srcaspect >dstaspect) {      return NewRect (0, 0, Dstwidth, (int) (Dstwidth/srcaspect)); } Else {      return NewRect (0, 0, (int) (Dstheight *srcaspect), dstheight); }  } Else {    return NewRect (0, 0, Dstwidth, dstheight); }}

The source rectangle will contain the entire source dimension, just in case it is appropriate. In the case of clipping, it calculates the target image with the same aspect ratio to crop the width or height of the source image to reach the size you want. And just in the appropriate case, will have the same aspect ratio of the source image, adjust to the size you want to the width or height.

Replace line 1
The decoder is smart, especially for JPEG and PNG formats. These decoders can be scaled when the picture is decoded, and performance is improved, so that the sawtooth problem can also be avoided. In addition, because the image is smaller after decoding, it will require less memory.

When zooming and decoding, simply set the Insamplesize parameter on the Bitmapfactory.options object and pass it to bitmapfactory. The sample size specifies an abstraction that scales the size of the image, for example, 2 is the factor of the 640x480 image decoding on the image. When setting the sample size, you cannot guarantee that the image will be scaled down strictly according to this number, but at least it will not be smaller. For example, a 3 times-fold image of 640x480 may cause a value to be unsupported in an image that is not supported. Typically, at least 2 of the one-time support [1,2,4,8, ...].

The next step is to specify a suitable sample size. The appropriate sample size will produce the maximum scale, but still be greater than or equal to the image size you want. As in the following code:

 Public StaticBitmap DecodeFile (String pathName,intDstwidth,intdstheight, Scalinglogic scalinglogic) {Options Options=NewOptions (); Options.injustdecodebounds=true;  Bitmapfactory.decodefile (pathName, Options); Options.injustdecodebounds=false; Options.insamplesize=calculatesamplesize (Options.outwidth, Options.outheight, Dstwidth, Dstheight, scalinglogic); Bitmap Unscaledbitmap=bitmapfactory.decodefile (pathName, Options); returnUnscaledbitmap;} Public Static intCalculatesamplesize (intSrcwidth,intSrcheight,intDstwidth,intdstheight, Scalinglogic scalinglogic) {  if(Scalinglogic = =scalinglogic.fit) {Final floatSrcaspect = (float) Srcwidth/(float) Srcheight; Final floatDstaspect = (float) Dstwidth/(float) Dstheight; if(Srcaspect >dstaspect) {      returnSrcwidth/Dstwidth; } Else {      returnSrcheight/Dstheight; }  } Else {    Final floatSrcaspect = (float) Srcwidth/(float) Srcheight; Final floatDstaspect = (float) Dstwidth/(float) Dstheight; if(Srcaspect >dstaspect) {      returnSrcheight/Dstheight; } Else {      returnSrcwidth/Dstwidth; }  }}

In DecodeFile (... ) method, we decode a file for the final scaling scale. This is first to decode the source image size and then use the Calculatesamplesize (... ) Calculates the optimal sample size and finally decodes the image using the size of this sample. If you are interested, you can learn more about Calculatesamplesize (...). ) method, but the above method basically ensures that the image is scaled.

put it all together
Depending on the method we specified above, you can now perform a replacement of the original line of code:

Bitmap Unscaledbitmap == Createscaledbitmap (Unscaledbitmap, Dstwidth, Dstheight, scalinglogic);

Image on the left: the original solution, decoding consumes 6693 KB of memory and about 1/4 seconds. The result is elongated and distorted. The middle Image: a scaling solution that decodes the memory consumed by 418 KB and is around 1/10 seconds. Image on the right: clipping solution, decoding consumes 418 KB of memory and about 1/10 seconds.

For more information, please download our code samples. With this source project, you can see the results of running on your Android phone.

Original address: http://developer.sonymobile.com/knowledge-base/tutorials/android_tutorial/ updated-how-to-scale-images-for-your-android-application-2/

andorid-How to scale a picture for your Android app

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.