Jul 9, 2012

Resize bitmap: Bitmap.createScaledBitmap vs BitmapFactory.Options.inSampleSize

In this article, two approach are provided to resize bitmap:
- Bitmap.createScaledBitmap
- BitmapFactory.Options.inSampleSize

But...which one is better? In the code, the process time are also provided for reference.

Bitmap.createScaledBitmap vs BitmapFactory.Options.inSampleSize


In order to count the process time, the code are run on UI Thread and the process time are calculated base on the start time and end time of the process. Please note that in normal case, you should not place such a long running process in UI Thread.

Place a test file in "/sdcard/tmp/testphoto.jpg".

Main Code, MainActivity.java.
package com.example.androidresizebitmap;

import android.os.Bundle;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;

public class MainActivity extends Activity {
 
 Button btnProcessA, btnProcessB;
 ImageView processedImgA, processedImgB;
 TextView statusA, statusB;
 
 /*
  * Normally do not hardcode "/sdcard/"; 
  * use Environment.getExternalStorageDirectory().getPath() instead
  */
 static String imgSouce = "/sdcard/tmp/testphoto.jpg";
 
 static int w = 250;
 static int h = 250;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        btnProcessA = (Button)findViewById(R.id.processbtna);
        btnProcessB = (Button)findViewById(R.id.processbtnb);
     processedImgA = (ImageView)findViewById(R.id.processedimg_a);
     processedImgB = (ImageView)findViewById(R.id.processedimg_b);
     statusA = (TextView)findViewById(R.id.statusa);
     statusB = (TextView)findViewById(R.id.statusb);
     
     btnProcessA.setOnClickListener(new OnClickListener(){

   @Override
   public void onClick(View v) {
    resizeA();
    
   }});
     
     btnProcessB.setOnClickListener(new OnClickListener(){

   @Override
   public void onClick(View v) {
    resizeB();
    
   }});

    }

    private void resizeA(){
     
     Long startTime = System.currentTimeMillis();
     
     Bitmap bitmap_Source = BitmapFactory.decodeFile(imgSouce);
     float factorH = h / (float)bitmap_Source.getHeight();
     float factorW = w / (float)bitmap_Source.getWidth();
     float factorToUse = (factorH > factorW) ? factorW : factorH;
     Bitmap bm = Bitmap.createScaledBitmap(bitmap_Source, 
       (int) (bitmap_Source.getWidth() * factorToUse), 
       (int) (bitmap_Source.getHeight() * factorToUse), 
       false);
     
     Long endTime = System.currentTimeMillis();
     Long processTime = endTime - startTime;
     statusA.setText("Process Time (MilliSeconds): " + String.valueOf(processTime));
     
     processedImgA.setImageBitmap(bm);

    }
    
    private void resizeB(){
     
     Long startTime = System.currentTimeMillis();
     
     BitmapFactory.Options bmpFactoryOptions = new BitmapFactory.Options();
  bmpFactoryOptions.inJustDecodeBounds = true;
  Bitmap bm = BitmapFactory.decodeFile(imgSouce, bmpFactoryOptions);
  
  int heightRatio = (int)Math.ceil(bmpFactoryOptions.outHeight/(float)h);
  int widthRatio = (int)Math.ceil(bmpFactoryOptions.outWidth/(float)w);
  
  if (heightRatio > 1 || widthRatio > 1)
  {
   if (heightRatio > widthRatio){
    bmpFactoryOptions.inSampleSize = heightRatio;  
   } else {
    bmpFactoryOptions.inSampleSize = widthRatio;   
   }   
  }
  
  bmpFactoryOptions.inJustDecodeBounds = false;
  bm = BitmapFactory.decodeFile(imgSouce, bmpFactoryOptions);
  
  Long endTime = System.currentTimeMillis();
     Long processTime = endTime - startTime;
     statusB.setText("Process Time (MilliSeconds): " + String.valueOf(processTime));
  
  processedImgB.setImageBitmap(bm);
    }

}


Layout, activity_main.xml.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent" 
    android:orientation="vertical">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:padding="@dimen/padding_medium"
        android:text="@string/hello_world"
        tools:context=".MainActivity" />
    
    <Button
        android:id="@+id/processbtna"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Resize using process A"/>
    <ImageView
        android:id="@+id/processedimg_a"
        android:layout_width="250px"
        android:layout_height="250px"/>
    <TextView
        android:id="@+id/statusa"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>
    
    <Button
        android:id="@+id/processbtnb"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Resize using process B"/>
    <ImageView
        android:id="@+id/processedimg_b"
        android:layout_width="250px"
        android:layout_height="250px"/>
    <TextView
        android:id="@+id/statusb"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>

</LinearLayout>


- More about Image processing on Android.


No comments:

Post a Comment

Infolinks In Text Ads