Monday, September 30, 2013

ColorMatrix.setConcat() to combine ColorMatrixes

The exercise "Set the rotation on a color axis of Bitmap with ColorMatrix" create rotated ColorMatrix for one color only, not all. We can create ColorMatrix from more than one by calling ColorMatrix.setConcat().

ColorMatrix.setConcat() to combine ColorMatrixs


package com.example.androiddrawbitmap;

import java.io.FileNotFoundException;

import android.net.Uri;
import android.os.Bundle;
import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.ColorMatrix;
import android.graphics.ColorMatrixColorFilter;
import android.graphics.Paint;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.TextView;

public class MainActivity extends Activity {

 Button btnLoadImage;
 ImageView imageResult;
 SeekBar rotBarRed, rotBarGreen, rotBarBlue;
 TextView rotText;

 final int RQS_IMAGE1 = 1;

 Uri source;
 Bitmap bitmapMaster;
 Canvas canvasMaster;

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

  btnLoadImage = (Button) findViewById(R.id.loadimage);
  imageResult = (ImageView) findViewById(R.id.result);

  btnLoadImage.setOnClickListener(new OnClickListener() {

   @Override
   public void onClick(View arg0) {
    Intent intent = new Intent(
      Intent.ACTION_PICK,
      android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
    startActivityForResult(intent, RQS_IMAGE1);
   }
  });

  rotText = (TextView) findViewById(R.id.textRot);
  rotBarRed = (SeekBar) findViewById(R.id.rotbarred);
  rotBarGreen = (SeekBar) findViewById(R.id.rotbargreen);
  rotBarBlue = (SeekBar) findViewById(R.id.rotbarblue);
  rotBarRed.setOnSeekBarChangeListener(seekBarChangeListener);
  rotBarGreen.setOnSeekBarChangeListener(seekBarChangeListener);
  rotBarBlue.setOnSeekBarChangeListener(seekBarChangeListener);

 }

 @Override
 protected void onActivityResult(int requestCode, int resultCode, Intent data) {
  super.onActivityResult(requestCode, resultCode, data);

  if (resultCode == RESULT_OK) {
   switch (requestCode) {
   case RQS_IMAGE1:
    source = data.getData();

    try {
     bitmapMaster = BitmapFactory
       .decodeStream(getContentResolver().openInputStream(
         source));

     rotBarRed.setProgress(0);
     rotBarGreen.setProgress(0);
     rotBarBlue.setProgress(0);

     loadBitmapRotate();

    } catch (FileNotFoundException e) {
     // TODO Auto-generated catch block
     e.printStackTrace();
    }

    break;
   }
  }
 }

 OnSeekBarChangeListener seekBarChangeListener = new OnSeekBarChangeListener() {

  @Override
  public void onProgressChanged(SeekBar seekBar, int progress,
    boolean fromUser) {
   // TODO Auto-generated method stub

  }

  @Override
  public void onStartTrackingTouch(SeekBar seekBar) {
   // TODO Auto-generated method stub

  }

  @Override
  public void onStopTrackingTouch(SeekBar seekBar) {
   loadBitmapRotate();
  }
 };

 private void loadBitmapRotate() {
  if (bitmapMaster != null) {

   float rotRed = (float) rotBarRed.getProgress();
   float rotGreen = (float) rotBarGreen.getProgress();
   float rotBlue = (float) rotBarBlue.getProgress();

   rotText.setText("setRotate: " + String.valueOf(rotRed) + ", "
     + String.valueOf(rotGreen) + ", " + String.valueOf(rotBlue));

   Bitmap bitmapColorScaled = updateRot(bitmapMaster, rotRed,
     rotGreen, rotBlue);

   imageResult.setImageBitmap(bitmapColorScaled);
  }
 }

 private Bitmap updateRot(Bitmap src, float degreesRed, float degreesGreen,
   float degreesBlue) {

  int w = src.getWidth();
  int h = src.getHeight();

  Bitmap bitmapResult = Bitmap
    .createBitmap(w, h, Bitmap.Config.ARGB_8888);
  Canvas canvasResult = new Canvas(bitmapResult);
  Paint paint = new Paint();

  ColorMatrix colorMatrixRed = new ColorMatrix();
  colorMatrixRed.setRotate(0, degreesRed);
  ColorMatrix colorMatrixGreen = new ColorMatrix();
  colorMatrixGreen.setRotate(1, degreesGreen);
  ColorMatrix colorMatrixBlue = new ColorMatrix();
  colorMatrixBlue.setRotate(2, degreesBlue);
  ColorMatrix colorMatrixConcat = new ColorMatrix();
  colorMatrixConcat.setConcat(colorMatrixRed, colorMatrixGreen);
  colorMatrixConcat.setConcat(colorMatrixConcat, colorMatrixBlue);

  ColorMatrixColorFilter filter = new ColorMatrixColorFilter(
    colorMatrixConcat);
  paint.setColorFilter(filter);
  canvasResult.drawBitmap(src, 0, 0, paint);

  return bitmapResult;
 }
}


<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"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity" >

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:autoLink="web"
        android:text="http://android-er.blogspot.com/"
        android:textStyle="bold" />

    <Button
        android:id="@+id/loadimage"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Load Image 1" />

    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent" >

        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="vertical" >

            <ImageView
                android:id="@+id/result"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:adjustViewBounds="true"
                android:background="@android:color/background_dark"
                android:scaleType="centerInside" />

            <TextView
                android:id="@+id/textRot"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="ColorMatrix Rotate" />

            <SeekBar
                android:id="@+id/rotbarred"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:max="360"
                android:progress="0" />
            <SeekBar
                android:id="@+id/rotbargreen"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:max="360"
                android:progress="0" />
            <SeekBar
                android:id="@+id/rotbarblue"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:max="360"
                android:progress="0" />
        </LinearLayout>
    </ScrollView>

</LinearLayout>


download filesDownload the files.

download filesDownload and try the APK.



more: Something about processing images in Android

Friday, September 27, 2013

Scale color and alpha of colormatrix with setScale()

Example of using ColorMatrix.setScale(float rScale, float gScale, float bScale, float aScale).

Example of using ColorMatrix.setScale()

package com.example.androiddrawbitmap;

import java.io.FileNotFoundException;

import android.net.Uri;
import android.os.Bundle;
import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.ColorMatrix;
import android.graphics.ColorMatrixColorFilter;
import android.graphics.Paint;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.TextView;

public class MainActivity extends Activity {

 Button btnLoadImage;
 ImageView imageResult;
 SeekBar scaleBarRed, scaleBarGreen, scaleBarBlue, scaleBarAlpha;
 TextView cmScaleText;

 final int RQS_IMAGE1 = 1;

 Uri source;
 Bitmap bitmapMaster;
 Canvas canvasMaster;

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

  btnLoadImage = (Button) findViewById(R.id.loadimage);
  imageResult = (ImageView) findViewById(R.id.result);

  btnLoadImage.setOnClickListener(new OnClickListener() {

   @Override
   public void onClick(View arg0) {
    Intent intent = new Intent(
      Intent.ACTION_PICK,
      android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
    startActivityForResult(intent, RQS_IMAGE1);
   }
  });

  cmScaleText = (TextView) findViewById(R.id.textCMScale);
  scaleBarRed = (SeekBar) findViewById(R.id.scalebarred);
  scaleBarGreen = (SeekBar) findViewById(R.id.scalebargreen);
  scaleBarBlue = (SeekBar) findViewById(R.id.scalebarblue);
  scaleBarAlpha = (SeekBar) findViewById(R.id.scalebaralpha);
  scaleBarRed.setOnSeekBarChangeListener(seekBarChangeListener);
  scaleBarGreen.setOnSeekBarChangeListener(seekBarChangeListener);
  scaleBarBlue.setOnSeekBarChangeListener(seekBarChangeListener);
  scaleBarAlpha.setOnSeekBarChangeListener(seekBarChangeListener);

 }

 @Override
 protected void onActivityResult(int requestCode, int resultCode, Intent data) {
  super.onActivityResult(requestCode, resultCode, data);

  if (resultCode == RESULT_OK) {
   switch (requestCode) {
   case RQS_IMAGE1:
    source = data.getData();

    try {
     bitmapMaster = BitmapFactory
       .decodeStream(getContentResolver().openInputStream(
         source));

     scaleBarRed.setProgress(100);
     scaleBarGreen.setProgress(100);
     scaleBarBlue.setProgress(100);
     scaleBarAlpha.setProgress(100);

     loadBitmapScaleColor();

    } catch (FileNotFoundException e) {
     // TODO Auto-generated catch block
     e.printStackTrace();
    }

    break;
   }
  }
 }

 OnSeekBarChangeListener seekBarChangeListener = 
   new OnSeekBarChangeListener() {

  @Override
  public void onProgressChanged(SeekBar seekBar, int progress,
    boolean fromUser) {
   // TODO Auto-generated method stub

  }

  @Override
  public void onStartTrackingTouch(SeekBar seekBar) {
   // TODO Auto-generated method stub

  }

  @Override
  public void onStopTrackingTouch(SeekBar seekBar) {
   loadBitmapScaleColor();
  }
 };

 private void loadBitmapScaleColor() {
  if (bitmapMaster != null) {

   int progressScaleRed = scaleBarRed.getProgress();
   int progressScaleGreen = scaleBarGreen.getProgress();
   int progressScaleBlue = scaleBarBlue.getProgress();
   int progressScaleAlpha = scaleBarAlpha.getProgress();

   float scaleRed = (float) progressScaleRed/100;
   float scaleGreen = (float) progressScaleGreen/100;
   float scaleBlue = (float) progressScaleBlue/100;
   float scaleAlpha = (float) progressScaleAlpha/100;
   
   cmScaleText.setText("setScale: "
     + String.valueOf(scaleRed) + ", "
     + String.valueOf(scaleGreen) + ", "
     + String.valueOf(scaleBlue) + ", "
     + String.valueOf(scaleAlpha));
   
   Bitmap bitmapColorScaled = updateScale(
     bitmapMaster, 
     scaleRed, 
     scaleGreen, 
     scaleBlue, 
     scaleAlpha);
   
   imageResult.setImageBitmap(bitmapColorScaled);
  }
 }

 private Bitmap updateScale(Bitmap src, float rScale, float gScale, 
   float bScale, float aScale) {

  int w = src.getWidth();
  int h = src.getHeight();

  Bitmap bitmapResult = Bitmap
    .createBitmap(w, h, Bitmap.Config.ARGB_8888);
  Canvas canvasResult = new Canvas(bitmapResult);
  Paint paint = new Paint();
  ColorMatrix colorMatrix = new ColorMatrix();
  colorMatrix.setScale(rScale, gScale, bScale, aScale);
  ColorMatrixColorFilter filter = new ColorMatrixColorFilter(colorMatrix);
  paint.setColorFilter(filter);
  canvasResult.drawBitmap(src, 0, 0, paint);

  return bitmapResult;
 }
}


<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"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity" >

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:autoLink="web"
        android:text="http://android-er.blogspot.com/"
        android:textStyle="bold" />

    <Button
        android:id="@+id/loadimage"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Load Image 1" />

    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent" >

        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="vertical" >

            <ImageView
                android:id="@+id/result"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:adjustViewBounds="true"
                android:background="@drawable/ic_launcher"
                android:scaleType="centerInside" />

            <TextView
                android:id="@+id/textCMScale"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="ColorMatrix Scale" />

            <SeekBar
                android:id="@+id/scalebarred"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:max="200"
                android:progress="100" />
            <SeekBar
                android:id="@+id/scalebargreen"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:max="200"
                android:progress="100" />
            <SeekBar
                android:id="@+id/scalebarblue"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:max="200"
                android:progress="100" />
            <SeekBar
                android:id="@+id/scalebaralpha"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:max="200"
                android:progress="100" />
        </LinearLayout>
    </ScrollView>

</LinearLayout>


download filesDownload the files.

download filesDownload and try the APK.



more: Something about processing images in Android

Thursday, September 26, 2013

Set the rotation on a color axis of Bitmap with ColorMatrix

Example to set the rotation on a color axis by the specified values. axis=0 correspond to a rotation around the RED color axis=1 correspond to a rotation around the GREEN color axis=2 correspond to a rotation around the BLUE color.

rotation on a color axis of Bitmap with ColorMatrix

package com.example.androiddrawbitmap;

import java.io.FileNotFoundException;

import android.net.Uri;
import android.os.Bundle;
import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.ColorMatrix;
import android.graphics.ColorMatrixColorFilter;
import android.graphics.Paint;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.RadioGroup.OnCheckedChangeListener;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.TextView;

public class MainActivity extends Activity {

 Button btnLoadImage;
 ImageView imageResult;
 SeekBar rotBar;
 TextView rotText;

 RadioGroup groupAxis;
 RadioButton optAxisRed, optAxisGreen, optAxisBlue;

 final int RQS_IMAGE1 = 1;

 Uri source;
 Bitmap bitmapMaster;
 Canvas canvasMaster;

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

  btnLoadImage = (Button) findViewById(R.id.loadimage);
  imageResult = (ImageView) findViewById(R.id.result);

  btnLoadImage.setOnClickListener(new OnClickListener() {

   @Override
   public void onClick(View arg0) {
    Intent intent = new Intent(
      Intent.ACTION_PICK,
      android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
    startActivityForResult(intent, RQS_IMAGE1);
   }
  });

  rotText = (TextView) findViewById(R.id.textRot);
  rotBar = (SeekBar) findViewById(R.id.rotbar);
  rotBar.setOnSeekBarChangeListener(seekBarChangeListener);

  groupAxis = (RadioGroup) findViewById(R.id.axisgroup);
  optAxisRed = (RadioButton) findViewById(R.id.axisred);
  optAxisGreen = (RadioButton) findViewById(R.id.axisgreen);
  optAxisBlue = (RadioButton) findViewById(R.id.axisblue);
  groupAxis.setOnCheckedChangeListener(groupAxisOnCheckedChangeListener);

 }

 @Override
 protected void onActivityResult(int requestCode, int resultCode, Intent data) {
  super.onActivityResult(requestCode, resultCode, data);

  if (resultCode == RESULT_OK) {
   switch (requestCode) {
   case RQS_IMAGE1:
    source = data.getData();

    try {
     bitmapMaster = BitmapFactory
       .decodeStream(getContentResolver().openInputStream(
         source));

     optAxisRed.setChecked(true);
     rotBar.setProgress(0);

     loadBitmapSat();

    } catch (FileNotFoundException e) {
     // TODO Auto-generated catch block
     e.printStackTrace();
    }

    break;
   }
  }
 }

 OnSeekBarChangeListener seekBarChangeListener = 
   new OnSeekBarChangeListener() {

  @Override
  public void onProgressChanged(SeekBar seekBar, int progress,
    boolean fromUser) {
   // TODO Auto-generated method stub

  }

  @Override
  public void onStartTrackingTouch(SeekBar seekBar) {
   // TODO Auto-generated method stub

  }

  @Override
  public void onStopTrackingTouch(SeekBar seekBar) {
   loadBitmapSat();
  }
 };

 OnCheckedChangeListener groupAxisOnCheckedChangeListener = 
   new OnCheckedChangeListener() {

  @Override
  public void onCheckedChanged(RadioGroup group, int checkedId) {
   loadBitmapSat();
  }
 };

 private void loadBitmapSat() {
  if (bitmapMaster != null) {

   int progressRot = rotBar.getProgress();

   float rotDegree = (float) progressRot;

   if (optAxisRed.isChecked()) {
    rotText.setText("setRotate: " + "Red: "
      + String.valueOf(rotDegree));
    imageResult
      .setImageBitmap(updateRot(bitmapMaster, 0, rotDegree));
   } else if (optAxisGreen.isChecked()) {
    rotText.setText("setRotate: " + "Green: "
      + String.valueOf(rotDegree));
    imageResult
      .setImageBitmap(updateRot(bitmapMaster, 1, rotDegree));
   } else if (optAxisBlue.isChecked()) {
    rotText.setText("setRotate: " + "Blue: "
      + String.valueOf(rotDegree));
    imageResult
      .setImageBitmap(updateRot(bitmapMaster, 2, rotDegree));
   }
  }
 }

 private Bitmap updateRot(Bitmap src, int axis, float degrees) {

  int w = src.getWidth();
  int h = src.getHeight();

  Bitmap bitmapResult = Bitmap
    .createBitmap(w, h, Bitmap.Config.ARGB_8888);
  Canvas canvasResult = new Canvas(bitmapResult);
  Paint paint = new Paint();
  ColorMatrix colorMatrix = new ColorMatrix();
  colorMatrix.setRotate(axis, degrees);
  ColorMatrixColorFilter filter = new ColorMatrixColorFilter(colorMatrix);
  paint.setColorFilter(filter);
  canvasResult.drawBitmap(src, 0, 0, paint);

  return bitmapResult;
 }
}


<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"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity" >

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:autoLink="web"
        android:text="http://android-er.blogspot.com/"
        android:textStyle="bold" />

    <Button
        android:id="@+id/loadimage"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Load Image 1" />

    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent" >

        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="vertical" >

            <ImageView
                android:id="@+id/result"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:adjustViewBounds="true"
                android:background="@android:color/background_dark"
                android:scaleType="centerInside" />

            <TextView
                android:id="@+id/textRot"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="Rotate Axis" />

            <RadioGroup
                android:id="@+id/axisgroup"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:orientation="horizontal" >

                <RadioButton
                    android:id="@+id/axisred"
                    android:layout_width="0dp"
                    android:layout_height="wrap_content"
                    android:layout_weight="1"
                    android:checked="true"
                    android:text="Red" />

                <RadioButton
                    android:id="@+id/axisgreen"
                    android:layout_width="0dp"
                    android:layout_height="wrap_content"
                    android:layout_weight="1"
                    android:text="Green" />

                <RadioButton
                    android:id="@+id/axisblue"
                    android:layout_width="0dp"
                    android:layout_height="wrap_content"
                    android:layout_weight="1"
                    android:text="Blue" />
            </RadioGroup>

            <SeekBar
                android:id="@+id/rotbar"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:max="360"
                android:progress="0" />
        </LinearLayout>
    </ScrollView>

</LinearLayout>


download filesDownload the files.

download filesDownload and try the APK.

Related: Combine ColorMatrixes by calling setConcat().


more: Something about processing images in Android

Android Studio 0.2.10 Released

Read it more: http://tools.android.com/recent/androidstudio0210released


Monday, September 23, 2013

Watch video of Surface 2 Launch Event

Watch video the Surface 2 Launch Event in New York City, Sept. 23 HERE.

Surface 2 Launch Event

Adjust saturation of Bitmap with ColorMatrix

android.graphics.ColorMatrix is a 5x4 matrix for transforming the color+alpha components of a Bitmap. The setSaturation(float sat) method of ColorMatrix set the matrix to affect the saturation of colors. A value of 0 maps the color to gray-scale. 1 is identity.

This example demonstrate how to generate a bitmap with adjusted saturation using ColorMatrix.setSaturation().

Adjust saturation of Bitmap with ColorMatrix

package com.example.androiddrawbitmap;

import java.io.FileNotFoundException;

import android.net.Uri;
import android.os.Bundle;
import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.ColorMatrix;
import android.graphics.ColorMatrixColorFilter;
import android.graphics.Paint;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.TextView;

public class MainActivity extends Activity {

 Button btnLoadImage;
 TextView textSource;
 ImageView imageResult;
 SeekBar satBar;
 TextView satText;

 final int RQS_IMAGE1 = 1;

 Uri source;
 Bitmap bitmapMaster;
 Canvas canvasMaster;

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

  btnLoadImage = (Button) findViewById(R.id.loadimage);
  textSource = (TextView) findViewById(R.id.sourceuri);
  imageResult = (ImageView) findViewById(R.id.result);

  btnLoadImage.setOnClickListener(new OnClickListener() {

   @Override
   public void onClick(View arg0) {
    Intent intent = new Intent(
      Intent.ACTION_PICK,
      android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
    startActivityForResult(intent, RQS_IMAGE1);
   }
  });

  satText = (TextView) findViewById(R.id.textsat);
  satBar = (SeekBar) findViewById(R.id.satbar);
  satBar.setOnSeekBarChangeListener(seekBarChangeListener);

 }

 @Override
 protected void onActivityResult(int requestCode, int resultCode, Intent data) {
  super.onActivityResult(requestCode, resultCode, data);

  if (resultCode == RESULT_OK) {
   switch (requestCode) {
   case RQS_IMAGE1:
    source = data.getData();

    try {
     bitmapMaster = BitmapFactory
       .decodeStream(getContentResolver().openInputStream(
         source));

     satBar.setProgress(256);

     loadBitmapSat();

    } catch (FileNotFoundException e) {
     // TODO Auto-generated catch block
     e.printStackTrace();
    }

    break;
   }
  }
 }

 OnSeekBarChangeListener seekBarChangeListener = new OnSeekBarChangeListener() {

  @Override
  public void onProgressChanged(SeekBar seekBar, int progress,
    boolean fromUser) {
   // TODO Auto-generated method stub

  }

  @Override
  public void onStartTrackingTouch(SeekBar seekBar) {
   // TODO Auto-generated method stub

  }

  @Override
  public void onStopTrackingTouch(SeekBar seekBar) {
   loadBitmapSat();
  }
 };

 private void loadBitmapSat() {
  if (bitmapMaster != null) {

   int progressSat = satBar.getProgress();

   //Saturation, 0=gray-scale. 1=identity
   float sat = (float) progressSat / 256;
   satText.setText("Saturation: " + String.valueOf(sat));
   imageResult.setImageBitmap(updateSat(bitmapMaster, sat));
  }
 }

 private Bitmap updateSat(Bitmap src, float settingSat) {

  int w = src.getWidth();
  int h = src.getHeight();

  Bitmap bitmapResult = 
    Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
  Canvas canvasResult = new Canvas(bitmapResult);
  Paint paint = new Paint();
  ColorMatrix colorMatrix = new ColorMatrix();
  colorMatrix.setSaturation(settingSat);
  ColorMatrixColorFilter filter = new ColorMatrixColorFilter(colorMatrix);
  paint.setColorFilter(filter);
  canvasResult.drawBitmap(src, 0, 0, paint);

  return bitmapResult;
 }
}


<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"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity" >

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:autoLink="web"
        android:text="http://android-er.blogspot.com/"
        android:textStyle="bold" />

    <Button
        android:id="@+id/loadimage"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Load Image 1" />

    <TextView
        android:id="@+id/sourceuri"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
    
    <ImageView
        android:id="@+id/result"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:adjustViewBounds="true"
        android:background="@android:color/background_dark"
        android:scaleType="centerInside" />
    
    <TextView 
        android:id="@+id/textsat"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Saturation" />
    <SeekBar
        android:id="@+id/satbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:max="512"
        android:progress="256"/>

</LinearLayout>


download filesDownload the files.

download filesDownload and try the APK.



more: Something about processing images in Android

Saturday, September 21, 2013

New Features in the Google Maps Mobile APIs for Android and iOS

Maps Live: New Features in the Google Maps Mobile APIs for Android and iOS

Google Maps API Team members Daniel Schramm and Chris Broadfoot discuss exciting new cross platform features in the Google Maps Android API v2 (http://goo.gl/5k18Es) and the Google Maps SDK for iOS (http://goo.gl/r2c2e). New to the latest versions are map padding, marker rotation, and flat markers.




The series:
A simple example using Google Maps Android API v2, step by step.

Thursday, September 19, 2013

Android SDK and ADT Plugin updated 22.2.1

To update Android SDK in Eclipse, select Window ->Android SDK Manager:

Android SDK 22.2.1

Update Eclipse ADT Plugin, select Help -> Check for Updates:

ADT 22.2.1

Scale bitmap with inDither and inPreferQualityOverSpeed

The exercise "Load scaled bitmap" demonstrate a simple and standard method to scale bitmap. Additionally, we can set inDither and inPreferQualityOverSpeed options to improve quality of the scaled bitmap.
  • inDither:
    If set, the decoder will attempt to dither the decoded image.
    Dithering is a technique used in computer graphics to create the illusion of color depth in images with a limited color palette (color quantization). ~ reference: Wikipedia, Dither in Digital photography and image processing.
  • inPreferQualityOverSpeed (Added in API level 10) : 
    If set, the decoder will try to decode the reconstructed image to a higher quality even at the expense of the decoding speed. Currently the field only affects JPEG decode, in the case of which a more accurate, but slightly slower, IDCT method will be used instead.

In this exercise, we can set options of inDither and inPreferQualityOverSpeed in scaling bitmap. And also display the INACCURACY processing duration of scaling bitmap in millisecond, for reference only.

Scale bitmap with inDither and inPreferQualityOverSpeed

package com.example.androidscalebitmap;

import java.io.FileNotFoundException;
import java.io.InputStream;
import java.util.Date;

import android.net.Uri;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.ToggleButton;
import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;

public class MainActivity extends Activity {

 final int RQS_IMAGE1 = 1;

 Button btnLoadImage;
 ToggleButton optBtnInDither, optBtnInPreferQualityOverSpeed;
 TextView textInfo;
 ImageView imageResult;

 Uri source1;
 Date startTime;

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  btnLoadImage = (Button) findViewById(R.id.loadimage);
  optBtnInDither = (ToggleButton) findViewById(R.id.optInDither);
  optBtnInPreferQualityOverSpeed = (ToggleButton) findViewById(R.id.optInPreferQualityOverSpeed);
  textInfo = (TextView) findViewById(R.id.info);
  imageResult = (ImageView) findViewById(R.id.result);

  btnLoadImage.setOnClickListener(new OnClickListener() {

   @Override
   public void onClick(View arg0) {
    Intent intent = new Intent(
      Intent.ACTION_PICK,
      android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
    startActivityForResult(intent, RQS_IMAGE1);
   }
  });
  
  optBtnInDither.setOnCheckedChangeListener(
    optBtnOnCheckedChangeListener);
  optBtnInPreferQualityOverSpeed.setOnCheckedChangeListener(
    optBtnOnCheckedChangeListener);
 }
 
 OnCheckedChangeListener optBtnOnCheckedChangeListener =
   new OnCheckedChangeListener(){

    @Override
    public void onCheckedChanged(CompoundButton arg0, boolean arg1) {
     doScale(source1);
    }};

 @Override
 protected void onActivityResult(int requestCode, int resultCode, Intent data) {
  super.onActivityResult(requestCode, resultCode, data);

  if (resultCode == RESULT_OK) {
   switch (requestCode) {
   case RQS_IMAGE1:
    source1 = data.getData();
    optBtnInDither.setChecked(false);
    optBtnInPreferQualityOverSpeed.setChecked(false);
    doScale(source1);
    break;
   }
  }
 }
 
 private void doScale(Uri src){
  
  try {
   Bitmap bm = loadScaledBitmap(source1);
   imageResult.setImageBitmap(bm);
  } catch (FileNotFoundException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
  
 }

 private Bitmap loadScaledBitmap(Uri src) throws FileNotFoundException {

  // required max width/height
  final int REQ_WIDTH = 800;
  final int REQ_HEIGHT = 800;

  Bitmap bm = null;

  if (src != null) {
   // First decode with inJustDecodeBounds=true to check dimensions
   final BitmapFactory.Options options = new BitmapFactory.Options();
   options.inJustDecodeBounds = true;
   BitmapFactory.decodeStream(getContentResolver()
     .openInputStream(src), null, options);

   // Calculate inSampleSize
   options.inSampleSize = calculateInSampleSize(options, REQ_WIDTH,
     REQ_HEIGHT);

   // Decode bitmap with inSampleSize set
   options.inJustDecodeBounds = false;
   
   //set options according to RadioButton setting
   options.inDither = optBtnInDither.isChecked();
   //inPreferQualityOverSpeed require API Level 10
   options.inPreferQualityOverSpeed = optBtnInPreferQualityOverSpeed.isChecked();
   
   InputStream inputStream = getContentResolver().openInputStream(src);
   startTime = new Date();
   
   bm = BitmapFactory.decodeStream(inputStream, null, options);
   
   //INACCURACY processing duration of scaling bitmap in millisecond
   long duration = new Date().getTime() - startTime.getTime();
   textInfo.setText("duration in ms: " + duration);
  }

  return bm;
 }

 public int calculateInSampleSize(BitmapFactory.Options options,
   int reqWidth, int reqHeight) {
  // Raw height and width of image
  final int height = options.outHeight;
  final int width = options.outWidth;
  int inSampleSize = 1;

  if (height > reqHeight || width > reqWidth) {

   // Calculate ratios of height and width to requested height and
   // width
   final int heightRatio = Math.round((float) height
     / (float) reqHeight);
   final int widthRatio = Math.round((float) width / (float) reqWidth);

   // Choose the smallest ratio as inSampleSize value, this will
   // guarantee a final image with both dimensions larger than or 
   // equal to the requested height and width.
   inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
  }

  return inSampleSize;
 }
}


<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"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity" >

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:autoLink="web"
        android:text="http://android-er.blogspot.com/"
        android:textStyle="bold" />

    <Button
        android:id="@+id/loadimage"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Load Image 1" />
    <ToggleButton 
        android:id="@+id/optInDither"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:checked="false"
        android:textOn="inDither ON"
        android:textOff="inDither OFF"/>
    <ToggleButton 
        android:id="@+id/optInPreferQualityOverSpeed"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:checked="false"
        android:textOn="inPreferQualityOverSpeed ON"
        android:textOff="inPreferQualityOverSpeed OFF"/>
    <TextView
        android:id="@+id/info"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

    <ImageView
        android:id="@+id/result"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:adjustViewBounds="true"
        android:background="@android:color/background_dark"
        android:scaleType="center" />

</LinearLayout>


download filesDownload the files.


download filesDownload and try the APK.



more: Something about processing images in Android

Android Developer Tools Essentials: Android Studio to Zipalign


Android development can be challenging, but through the effective use of Android Developer Tools (ADT), you can make the process easier and improve the quality of your code. This concise guide demonstrates how to build apps with ADT for a device family that features several screen sizes, different hardware capabilities, and a varying number of resources.
With examples in Windows, Linux, and Mac OS X, you’ll learn how to set up an Android development environment and use ADT with the Eclipse IDE. Also, contributor Donn Felker introduces Android Studio, a Google IDE that will eventually replace Eclipse.
  • Learn how to use Eclipse and ADT together to develop Android code
  • Create emulators of various sizes and configurations to test your code
  • Master Eclipse tools, or explore the new Android Studio
  • Use Logcat, Lint, and other ADT tools to test and debug your code
  • Simulate real-world events, including location, sensors, and telephony
  • Create dynamic and efficient UIs, using Graphical Layout tools
  • Monitor and optimize you application performance using DDMS, HierarchyViewer, and the Android Monitor tool
  • Use Wizards and shortcuts to generate code and image assets
  • Compile and package Android code with Ant and Gradle

Wednesday, September 18, 2013

Adjust HSV(Hue, Saturation and Value) of bitmap

android.graphics.Color class provide colorToHSV() and HSVToColor() methods to convert between ARGB color and HSV components. Such that we can adjust HSV of bitmap.

Adjust HSV(Hue, Saturation and Value) of bitmap

package com.example.androiddrawbitmap;

import java.io.FileNotFoundException;

import android.net.Uri;
import android.os.Bundle;
import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.TextView;

public class MainActivity extends Activity {

 Button btnLoadImage;
 TextView textSource;
 ImageView imageResult;
 SeekBar hueBar, satBar, valBar;
 TextView hueText, satText, valText;
 Button btnResetHSV;

 final int RQS_IMAGE1 = 1;

 Uri source;
 Bitmap bitmapMaster;
 Canvas canvasMaster;

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

  btnLoadImage = (Button) findViewById(R.id.loadimage);
  textSource = (TextView) findViewById(R.id.sourceuri);
  imageResult = (ImageView) findViewById(R.id.result);
  
  btnLoadImage.setOnClickListener(new OnClickListener() {

   @Override
   public void onClick(View arg0) {
    Intent intent = new Intent(
      Intent.ACTION_PICK,
      android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
    startActivityForResult(intent, RQS_IMAGE1);
   }
  });
  
  hueText = (TextView) findViewById(R.id.texthue);
  satText = (TextView) findViewById(R.id.textsat);
  valText = (TextView) findViewById(R.id.textval);
  hueBar = (SeekBar) findViewById(R.id.huebar);
  satBar = (SeekBar) findViewById(R.id.satbar);
  valBar = (SeekBar) findViewById(R.id.valbar);
  hueBar.setOnSeekBarChangeListener(seekBarChangeListener);
  satBar.setOnSeekBarChangeListener(seekBarChangeListener);
  valBar.setOnSeekBarChangeListener(seekBarChangeListener);
  btnResetHSV = (Button)findViewById(R.id.resethsv);
  btnResetHSV.setOnClickListener(new OnClickListener(){

   @Override
   public void onClick(View arg0) {
    // reset SeekBars
    hueBar.setProgress(256);
    satBar.setProgress(256);
    valBar.setProgress(256);

    loadBitmapHSV();
   }});
 }

 @Override
 protected void onActivityResult(int requestCode, int resultCode, Intent data) {
  super.onActivityResult(requestCode, resultCode, data);

  if (resultCode == RESULT_OK) {
   switch (requestCode) {
   case RQS_IMAGE1:
    source = data.getData();

    try {
     bitmapMaster = BitmapFactory
       .decodeStream(getContentResolver().openInputStream(
         source));

     // reset SeekBars
     hueBar.setProgress(256);
     satBar.setProgress(256);
     valBar.setProgress(256);

     loadBitmapHSV();

    } catch (FileNotFoundException e) {
     // TODO Auto-generated catch block
     e.printStackTrace();
    }

    break;
   }
  }
 }

 OnSeekBarChangeListener seekBarChangeListener = new OnSeekBarChangeListener() {

  @Override
  public void onProgressChanged(SeekBar seekBar, int progress,
    boolean fromUser) {
   // TODO Auto-generated method stub

  }

  @Override
  public void onStartTrackingTouch(SeekBar seekBar) {
   // TODO Auto-generated method stub

  }

  @Override
  public void onStopTrackingTouch(SeekBar seekBar) {
   loadBitmapHSV();
  }

 };

 private void loadBitmapHSV() {
  if (bitmapMaster != null) {

   int progressHue = hueBar.getProgress() - 256;
   int progressSat = satBar.getProgress() - 256;
   int progressVal = valBar.getProgress() - 256;

   /*
    * Hue (0 .. 360) Saturation (0...1) Value (0...1)
    */

   float hue = (float) progressHue * 360 / 256;
   float sat = (float) progressSat / 256;
   float val = (float) progressVal / 256;

   hueText.setText("Hue: " + String.valueOf(hue));
   satText.setText("Saturation: " + String.valueOf(sat));
   valText.setText("Value: " + String.valueOf(val));

   imageResult.setImageBitmap(updateHSV(bitmapMaster, hue, sat, val));

  }
 }

 private Bitmap updateHSV(Bitmap src, float settingHue, float settingSat,
   float settingVal) {

  int w = src.getWidth();
  int h = src.getHeight();
  int[] mapSrcColor = new int[w * h];
  int[] mapDestColor = new int[w * h];

  float[] pixelHSV = new float[3];

  src.getPixels(mapSrcColor, 0, w, 0, 0, w, h);

  int index = 0;
  for (int y = 0; y < h; ++y) {
   for (int x = 0; x < w; ++x) {

    // Convert from Color to HSV
    Color.colorToHSV(mapSrcColor[index], pixelHSV);

    // Adjust HSV
    pixelHSV[0] = pixelHSV[0] + settingHue;
    if (pixelHSV[0] < 0.0f) {
     pixelHSV[0] = 0.0f;
    } else if (pixelHSV[0] > 360.0f) {
     pixelHSV[0] = 360.0f;
    }

    pixelHSV[1] = pixelHSV[1] + settingSat;
    if (pixelHSV[1] < 0.0f) {
     pixelHSV[1] = 0.0f;
    } else if (pixelHSV[1] > 1.0f) {
     pixelHSV[1] = 1.0f;
    }

    pixelHSV[2] = pixelHSV[2] + settingVal;
    if (pixelHSV[2] < 0.0f) {
     pixelHSV[2] = 0.0f;
    } else if (pixelHSV[2] > 1.0f) {
     pixelHSV[2] = 1.0f;
    }

    // Convert back from HSV to Color
    mapDestColor[index] = Color.HSVToColor(pixelHSV);

    index++;
   }
  }

  return Bitmap.createBitmap(mapDestColor, w, h, Config.ARGB_8888);

 }

}


<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"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity" >

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:autoLink="web"
        android:text="http://android-er.blogspot.com/"
        android:textStyle="bold" />

    <Button
        android:id="@+id/loadimage"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Load Image 1" />

    <TextView
        android:id="@+id/sourceuri"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
    
    <ImageView
        android:id="@+id/result"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:adjustViewBounds="true"
        android:background="@android:color/background_dark"
        android:scaleType="centerInside" />
    
    <TextView 
        android:id="@+id/texthue"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Hue" />
    <SeekBar
        android:id="@+id/huebar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:max="511"
        android:progress="256"/>
    <TextView 
        android:id="@+id/textsat"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Saturation" />
    <SeekBar
        android:id="@+id/satbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:max="511"
        android:progress="256"/>
    <TextView 
        android:id="@+id/textval"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Value" />
    <SeekBar
        android:id="@+id/valbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:max="511"
        android:progress="256"/>
    <Button 
        android:id="@+id/resethsv"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Reset HSV" />
</LinearLayout>


download filesDownload the files.

download filesDownload and try APK.



more: Something about processing images in Android

Wednesday, September 11, 2013

Create SimpleDateFormat for specified Locale

Example of creating SimpleDateFormat with specified Locale from previous exercise "Get default Locale and available Locales".

Create SimpleDateFormat with specified Locale


package com.example.androidlocale;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import android.app.Activity;

public class MainActivity extends Activity {

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  
  TextView textViewDefaultLocale = (TextView)findViewById(R.id.defaultlocale);
  TextView textViewNoOfLocale = (TextView)findViewById(R.id.numberoflocale);
  ListView listViewAvailableLocale = (ListView)findViewById(R.id.listviewlocale);
  
  Locale defaultLocale = Locale.getDefault();
  textViewDefaultLocale.setText("Default Locale: " + defaultLocale.toString());

  final Locale[] availableLocales = Locale.getAvailableLocales();
  textViewNoOfLocale.setText("Number of available Locale: " + availableLocales.length);
  String[] availableLocalesString = new String[availableLocales.length];
  
  for (int i=0; i<availableLocales.length; i++){
   availableLocalesString[i] = availableLocales[i].toString();
  }
  
  ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, 
            android.R.layout.simple_list_item_1, availableLocalesString);
  listViewAvailableLocale.setAdapter(adapter);
  
  listViewAvailableLocale.setOnItemClickListener(
    new OnItemClickListener(){

   @Override
   public void onItemClick(AdapterView<?> parent, 
     View view, int position, long id) {
    Locale item = availableLocales[position];
    
    String format = "yyyy-MM-dd'T'HH:mm:ss.SSSZ";
    SimpleDateFormat simpleDateFormat = new SimpleDateFormat(format, item);
    Date now = new Date();
    Toast.makeText(getApplicationContext(),
      "Locale: " + item.toString() + "\n"
      + simpleDateFormat.format(now),
      Toast.LENGTH_LONG).show();

   }});

 }

}

Monday, September 9, 2013

Get details of Locale

Last exercise list available Locale of the system. It's modified to display details of the clicked Locale.

Get details of Locale


package com.example.androidlocale;

import java.util.Locale;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import android.app.Activity;

public class MainActivity extends Activity {

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  
  TextView textViewDefaultLocale = (TextView)findViewById(R.id.defaultlocale);
  TextView textViewNoOfLocale = (TextView)findViewById(R.id.numberoflocale);
  ListView listViewAvailableLocale = (ListView)findViewById(R.id.listviewlocale);
  
  Locale defaultLocale = Locale.getDefault();
  textViewDefaultLocale.setText("Default Locale: " + defaultLocale.toString());

  final Locale[] availableLocales = Locale.getAvailableLocales();
  textViewNoOfLocale.setText("Number of available Locale: " + availableLocales.length);
  String[] availableLocalesString = new String[availableLocales.length];
  
  for (int i=0; i<availableLocales.length; i++){
   availableLocalesString[i] = availableLocales[i].toString();
  }
  
  ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, 
            android.R.layout.simple_list_item_1, availableLocalesString);
  listViewAvailableLocale.setAdapter(adapter);
  
  listViewAvailableLocale.setOnItemClickListener(
    new OnItemClickListener(){

   @Override
   public void onItemClick(AdapterView<?> parent, 
     View view, int position, long id) {
    Locale item = availableLocales[position];

    Toast.makeText(getApplicationContext(), 
      "Language: " + item.getLanguage() + "\n"
      + "Country: " + item.getCountry() + "\n"
      + "DisplayName: " + item.getDisplayName() + "\n"
      + "DisplayLanguage: " + item.getDisplayLanguage() + "\n"
      + "DisplayCountry: " + item.getDisplayCountry(), 
      Toast.LENGTH_LONG).show();
   }});

 }

}


Keep using the layout in last exercise.

Next: Create SimpleDateFormat for specified Locale

Saturday, September 7, 2013

Get default Locale and available Locales

Example to get default Locale and available Locales:

Get default Locale and available Locales


package com.example.androidlocale;

import java.util.Locale;
import android.os.Bundle;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.TextView;
import android.app.Activity;

public class MainActivity extends Activity {

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  
  TextView textViewDefaultLocale = (TextView)findViewById(R.id.defaultlocale);
  TextView textViewNoOfLocale = (TextView)findViewById(R.id.numberoflocale);
  ListView listViewAvailableLocale = (ListView)findViewById(R.id.listviewlocale);
  
  Locale defaultLocale = Locale.getDefault();
  textViewDefaultLocale.setText("Default Locale: " + defaultLocale.toString());

  Locale[] availableLocales = Locale.getAvailableLocales();
  textViewNoOfLocale.setText("Number of available Locale: " + availableLocales.length);
  String[] availableLocalesString = new String[availableLocales.length];
  
  for (int i=0; i<availableLocales.length; i++){
   availableLocalesString[i] = availableLocales[i].toString();
  }
  
  ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, 
            android.R.layout.simple_list_item_1, availableLocalesString);
  listViewAvailableLocale.setAdapter(adapter);

 }

}


<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:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:orientation="vertical"
    tools:context=".MainActivity" >

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:autoLink="web"
        android:text="http://android-er.blogspot.com/"
        android:textStyle="bold" />
    <TextView 
        android:id="@+id/defaultlocale"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>
    <TextView 
        android:id="@+id/numberoflocale"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>
    <ListView
        android:id="@+id/listviewlocale"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

</LinearLayout>

next: Get details of Locale

Combine bitmap, half/half

This example demonstrate how to combin two bitmap, half from a bitmap, another from the mirror bitmap of the same source.

Combine bitmap, half/half


package com.example.androiddrawbitmap;

import java.io.FileNotFoundException;

import android.net.Uri;
import android.os.Bundle;
import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Rect;
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 btnLoadImage;
 TextView textSource;
 ImageView imageResult;

 final int RQS_IMAGE1 = 1;

 Uri source;
 Bitmap bitmapMaster;
 Canvas canvasMaster;

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

  btnLoadImage = (Button) findViewById(R.id.loadimage);
  textSource = (TextView) findViewById(R.id.sourceuri);
  imageResult = (ImageView) findViewById(R.id.result);

  btnLoadImage.setOnClickListener(new OnClickListener() {

   @Override
   public void onClick(View arg0) {
    Intent intent = new Intent(
      Intent.ACTION_PICK,
      android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
    startActivityForResult(intent, RQS_IMAGE1);
   }
  });

 }

 @Override
 protected void onActivityResult(int requestCode, int resultCode, Intent data) {
  super.onActivityResult(requestCode, resultCode, data);

  Bitmap tempBitmap;

  if (resultCode == RESULT_OK) {
   switch (requestCode) {
   case RQS_IMAGE1:
    source = data.getData();

    try {
     tempBitmap = BitmapFactory
       .decodeStream(getContentResolver().openInputStream(
         source));

     //create a mirror bitmap
     Matrix matrixMirror = new Matrix();
     matrixMirror.preScale(-1.0f, 1.0f);
     Bitmap bitmapMirror = Bitmap.createBitmap(tempBitmap, 0, 0,
       tempBitmap.getWidth(), tempBitmap.getHeight(),
       matrixMirror, false);

     //define half/half area
     Rect rect1Half = new Rect(0, 0, tempBitmap.getWidth() / 2,
       tempBitmap.getHeight());
     Rect rect2Half = new Rect((tempBitmap.getWidth() / 2) + 1,
       0, tempBitmap.getWidth(), tempBitmap.getHeight());

     Config config = tempBitmap.getConfig();
     if (config == null) {
      config = Bitmap.Config.ARGB_8888;
     }

     //craete the master bitmap
     bitmapMaster = Bitmap.createBitmap(
       tempBitmap.getWidth(), tempBitmap.getHeight(), config);
     canvasMaster = new Canvas(bitmapMaster);

     //merge bitmap half/half
     canvasMaster.drawBitmap(tempBitmap, rect1Half, rect1Half,
       null);
     canvasMaster.drawBitmap(bitmapMirror, rect2Half, rect2Half,
       null);

     imageResult.setImageBitmap(bitmapMaster);

    } catch (FileNotFoundException e) {
     // TODO Auto-generated catch block
     e.printStackTrace();
    }

    break;
   }
  }
 }

}


<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"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity" >

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:autoLink="web"
        android:text="http://android-er.blogspot.com/"
        android:textStyle="bold" />

    <Button
        android:id="@+id/loadimage"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Load Image 1" />

    <TextView
        android:id="@+id/sourceuri"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
    
    <ImageView
            android:id="@+id/result"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:adjustViewBounds="true"
            android:background="@android:color/background_dark"
            android:scaleType="centerInside" />

</LinearLayout>


download filesDownload the files.



more: Something about processing images in Android

Friday, September 6, 2013

Sony releases Camera Remote API (beta)

With Sony Camera Remote API (beta), developers can create smartphone apps to control Sony cameras
  • Develop your own applications to control camera or get captured image and create Photo Uploader, Time Lapse Control Software, or other novel ideas for applications using the latest and greatest Sony cameras.
  • Start Today with the easy to learn and use, JSON based Application Programming Interface (API).
  • Since the API is platform agnostic, you can develop for your choice of operating systems like Android™, iOS™, Windows™ or others.


Visit: http://camera.developer.sony.com/

Press release: Sony to release API for using mobile devices as Wi-Fi remote controls for Sony cameras


Wednesday, September 4, 2013

Samsung is going to unpack Galaxy Note 3 at Samsung UNPACKED 2013 Episode 2


Samsung UNPACKED 2013 Episode 2 Livestream
Samsung UNPACKED 2013 Episode 2 from the Tempodrom in Berlin where we will unveil the next-generation products. Livestream begins at 19:00 CEST / 13:00 EDT on 4th September, Wednesday.


NEW from IFA 2013: Cyber-shot QX10, QX100 Lens-style Cameras for smartphone photographers


For more info:
http://bit.ly/14ovhww
http://bit.ly/18q8hzG

Bet you've never seen anything like this before! World, meet the Cyber-shot QX10 and QX100 Lens-style Cameras.

These babies will easily link to your smartphone (Android *and* iOS compatible!) and allow you to capture high-zoom, high quality photos which you can immediately share on Facebook, Instagram, and other social networks.

Another cool feature: these lens-style cameras can act as a remote viewfinder, letting you capture unique photos from different angles and perspectives.

Tuesday, September 3, 2013

Android KITKAT 4.4 -- The future of confectionery

KITKAT's Chief Breaks Officer tells us why KITKAT 4.4 is the future of confectionery.
For more information visit http://www.kitkat.com

Convert Bitmap to Drawable with BitmapDrawable

To convert Bitmap to Drawable with BitmapDrawable with the code:

     //Convert bitmap to drawable
     Drawable drawable = new BitmapDrawable(getResources(), tempBitmap);

Modify from previouse exercise "Create mirror bitmap with matrix" to load jpg from SDCARD, as Bitmap. Then convert to Drawable with BitmapDrawable.

Convert Bitmap to Drawable with BitmapDrawable


package com.example.androiddrawbitmap;

import java.io.FileNotFoundException;

import android.net.Uri;
import android.os.Bundle;
import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
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 btnLoadImage;
 TextView textSource;
 ImageView imageResult;
 
 final int RQS_IMAGE1 = 1;

 Uri source;
 Bitmap bitmapMaster;
 Canvas canvasMaster;
 
 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  
  btnLoadImage = (Button)findViewById(R.id.loadimage);
  textSource = (TextView)findViewById(R.id.sourceuri);
  imageResult = (ImageView)findViewById(R.id.result);
  
  btnLoadImage.setOnClickListener(new OnClickListener(){

   @Override
   public void onClick(View arg0) {
    Intent intent = new Intent(Intent.ACTION_PICK,
      android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
    startActivityForResult(intent, RQS_IMAGE1);
   }});
  
 }

 @Override
 protected void onActivityResult(int requestCode, int resultCode, Intent data) {
  super.onActivityResult(requestCode, resultCode, data);
  
  Bitmap tempBitmap;
  
  if(resultCode == RESULT_OK){
   switch (requestCode){
   case RQS_IMAGE1:
    source = data.getData();
    
    
    try {
     tempBitmap = BitmapFactory.decodeStream(
       getContentResolver().openInputStream(source));
     
     //Convert bitmap to drawable
     Drawable drawable = new BitmapDrawable(getResources(), tempBitmap);
     
     imageResult.setImageDrawable(drawable);
     
     textSource.setText(drawable.getClass().toString());
     
    } catch (FileNotFoundException e) {
     // TODO Auto-generated catch block
     e.printStackTrace();
    }
    
    break;
   }
  }
 }

}

Layout refer to the exercise "Create mirror bitmap with matrix".

download filesDownload the files.



more: Something about processing images in Android

Create upside down bitmap with matrix

To create upside down bitmap with matrix:
     Matrix matrixUpsideDown = new Matrix(); 
     matrixUpsideDown.preScale(1.0f, -1.0f);
     bitmapMaster = Bitmap.createBitmap(
       tempBitmap, 
       0, 
       0, 
       tempBitmap.getWidth(), 
       tempBitmap.getHeight(), 
       matrixUpsideDown, 
       false);

Create upside down bitmap with matrix
 Refer to last exercise "Create mirror bitmap with matrix" for full example.



more: Something about processing images in Android

Create mirror bitmap with matrix

To create mirror bitmap with matrix:

     Matrix matrixMirror = new Matrix(); 
     matrixMirror.preScale(-1.0f, 1.0f);
     bitmapMaster = Bitmap.createBitmap(
       tempBitmap, 
       0, 
       0, 
       tempBitmap.getWidth(), 
       tempBitmap.getHeight(), 
       matrixMirror, 
       false);

Create mirror bitmap with matrix

package com.example.androiddrawbitmap;

import java.io.FileNotFoundException;

import android.net.Uri;
import android.os.Bundle;
import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PorterDuff.Mode;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnTouchListener;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;

public class MainActivity extends Activity {
 
 Button btnLoadImage;
 TextView textSource;
 ImageView imageResult;
 
 final int RQS_IMAGE1 = 1;

 Uri source;
 Bitmap bitmapMaster;
 Canvas canvasMaster;
 
 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  
  btnLoadImage = (Button)findViewById(R.id.loadimage);
  textSource = (TextView)findViewById(R.id.sourceuri);
  imageResult = (ImageView)findViewById(R.id.result);
  
  btnLoadImage.setOnClickListener(new OnClickListener(){

   @Override
   public void onClick(View arg0) {
    Intent intent = new Intent(Intent.ACTION_PICK,
      android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
    startActivityForResult(intent, RQS_IMAGE1);
   }});
  
 }

 @Override
 protected void onActivityResult(int requestCode, int resultCode, Intent data) {
  super.onActivityResult(requestCode, resultCode, data);
  
  Bitmap tempBitmap;
  
  if(resultCode == RESULT_OK){
   switch (requestCode){
   case RQS_IMAGE1:
    source = data.getData();
    textSource.setText(source.toString());
    
    try {
     tempBitmap = BitmapFactory.decodeStream(
       getContentResolver().openInputStream(source));
     
     Matrix matrixMirror = new Matrix(); 
     matrixMirror.preScale(-1.0f, 1.0f);
     bitmapMaster = Bitmap.createBitmap(
       tempBitmap, 
       0, 
       0, 
       tempBitmap.getWidth(), 
       tempBitmap.getHeight(), 
       matrixMirror, 
       false);
     
     imageResult.setImageBitmap(bitmapMaster);
     
    } catch (FileNotFoundException e) {
     // TODO Auto-generated catch block
     e.printStackTrace();
    }
    
    break;
   }
  }
 }

}


<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"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity" >

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:autoLink="web"
        android:text="http://android-er.blogspot.com/"
        android:textStyle="bold" />

    <Button
        android:id="@+id/loadimage"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Load Image 1" />

    <TextView
        android:id="@+id/sourceuri"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
    
    <ImageView
            android:id="@+id/result"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:adjustViewBounds="true"
            android:background="@android:color/background_dark"
            android:scaleType="centerInside" />

</LinearLayout>

download filesDownload the files.

Next: Create upside down bitmap with matrix


more: Something about processing images in Android

Monday, September 2, 2013

Youtube 1980 hidden game


- Play any video in Youtube
- Pause
- type "1980"
- the game will start

Implement callback function with interface

This example demonstrate how to implement callback function with interface.

Implement callback function with interface

Create a MyAsyncTask class extends AsyncTask. Inside MyAsyncTask, interface DoSomething declared. MyAsyncTask class handle the background timing only, know knowing about the actual jobs. The actual jobs are in the class implement DoSomething.

package com.example.androidcallback;

import android.os.AsyncTask;
import android.os.SystemClock;

public class MyAsyncTask extends AsyncTask<Void, Void, Void> {

 interface DoSomething {
  void doInBackground(int progress);
  void doPostExecute();
 }

 DoSomething myDoSomethingCallBack;
 int myMax;
 
 MyAsyncTask(DoSomething callback, int max){
  myDoSomethingCallBack = callback;
  myMax = max;
 }

 @Override
 protected Void doInBackground(Void... params) {
  for (int i = 0; i <= myMax; i++) {
   SystemClock.sleep(100);
   myDoSomethingCallBack.doInBackground(i);
  }
  return null;
 }

 @Override
 protected void onPostExecute(Void result) {
  super.onPostExecute(result);
  myDoSomethingCallBack.doPostExecute();
 }

}


MainActivity.java, implements DoSomething. Itself (this) will be passed to MyAsyncTask constructor, to implement callback function.
package com.example.androidcallback;

import com.example.androidcallback.MyAsyncTask.DoSomething;

import android.os.Bundle;
import android.widget.ProgressBar;
import android.widget.Toast;
import android.app.Activity;

public class MainActivity extends Activity implements DoSomething{
 
 ProgressBar myProgressBar;
 MyAsyncTask myAsyncTask;
 int myProgress;

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  
  myProgressBar = (ProgressBar)findViewById(R.id.myprogressbar);
  
  myProgress = 0;
  myAsyncTask = new MyAsyncTask(this, 100);
  myAsyncTask.execute();
 }

 @Override
 public void doInBackground(int i) {
  myProgressBar.setProgress(i);
 }

 @Override
 public void doPostExecute() {
  Toast.makeText(MainActivity.this, 
    "Finish", Toast.LENGTH_LONG).show();
 }

}


layout
<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:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:orientation="vertical"
    tools:context=".MainActivity" >

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:autoLink="web"
        android:text="http://android-er.blogspot.com/"
        android:textStyle="bold" />
    
    <ProgressBar 
        android:id="@+id/myprogressbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        style="?android:attr/progressBarStyleHorizontal"
        android:max="100"
        android:progress="0" />

</LinearLayout>


download filesDownload the files.

Detect touch and draw rect on bitmap

In last example "Detect touch and free draw on Bitmap", the points are drawn on the canvas (also the bitmap) directly when user touch.

Detect touch and draw rect on bitmap


In case of drawing square, the user touch on the screen to mark the start position, and move, and release on the end position. We have to keep displaying the updated square. But if we draw the rect on the canvasMaster, it will full of rect when user touch and move.

In this example, we create two overlay ImageViews, have same dimension. Also additional bitmap and canvas for the extra ImagewView. When ACTION_DOWN detected, we mark the starting position. When ACTION_MOVE, we draw rect on the extra canvasDrawingPane, not the canvasMaster. Such that we can clear and re-draw the canvas everytime. And finally when ACTION_UP, simple draw the extra bitmap on canvasMaster.



package com.example.androiddrawbitmap;

import java.io.FileNotFoundException;

import android.net.Uri;
import android.os.Bundle;
import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PorterDuff.Mode;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnTouchListener;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;

public class MainActivity extends Activity {
 
 Button btnLoadImage;
 TextView textSource;
 ImageView imageResult, imageDrawingPane;
 
 final int RQS_IMAGE1 = 1;

 Uri source;
 Bitmap bitmapMaster;
 Canvas canvasMaster;
 Bitmap bitmapDrawingPane;
 Canvas canvasDrawingPane;
 projectPt startPt;
 
 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  
  btnLoadImage = (Button)findViewById(R.id.loadimage);
  textSource = (TextView)findViewById(R.id.sourceuri);
  imageResult = (ImageView)findViewById(R.id.result);
  imageDrawingPane = (ImageView)findViewById(R.id.drawingpane);
  
  btnLoadImage.setOnClickListener(new OnClickListener(){

   @Override
   public void onClick(View arg0) {
    Intent intent = new Intent(Intent.ACTION_PICK,
      android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
    startActivityForResult(intent, RQS_IMAGE1);
   }});
  
  imageResult.setOnTouchListener(new OnTouchListener(){

   @Override
   public boolean onTouch(View v, MotionEvent event) {
    
    int action = event.getAction();
    int x = (int) event.getX();
    int y = (int) event.getY();
    switch(action){
    case MotionEvent.ACTION_DOWN:
     textSource.setText("ACTION_DOWN- " + x + " : " + y);
     startPt = projectXY((ImageView)v, bitmapMaster, x, y);
     break;
    case MotionEvent.ACTION_MOVE:
     textSource.setText("ACTION_MOVE- " + x + " : " + y);
     drawOnRectProjectedBitMap((ImageView)v, bitmapMaster, x, y);
     break;
    case MotionEvent.ACTION_UP:
     textSource.setText("ACTION_UP- " + x + " : " + y);
     drawOnRectProjectedBitMap((ImageView)v, bitmapMaster, x, y);
     finalizeDrawing();
     break;
    }
    /*
     * Return 'true' to indicate that the event have been consumed.
     * If auto-generated 'false', your code can detect ACTION_DOWN only,
     * cannot detect ACTION_MOVE and ACTION_UP.
     */
    return true;
   }});
  
 }
 
 class projectPt{
  int x;
  int y;
  
  projectPt(int tx, int ty){
   x = tx;
   y = ty;
  }
 }
 
 private projectPt projectXY(ImageView iv, Bitmap bm, int x, int y){
  if(x<0 || y<0 || x > iv.getWidth() || y > iv.getHeight()){
   //outside ImageView
   return null;
  }else{
   int projectedX = (int)((double)x * ((double)bm.getWidth()/(double)iv.getWidth()));
   int projectedY = (int)((double)y * ((double)bm.getHeight()/(double)iv.getHeight()));

   return new projectPt(projectedX, projectedY);
  }
 }
 
 private void drawOnRectProjectedBitMap(ImageView iv, Bitmap bm, int x, int y){
  if(x<0 || y<0 || x > iv.getWidth() || y > iv.getHeight()){
   //outside ImageView
   return;
  }else{
   int projectedX = (int)((double)x * ((double)bm.getWidth()/(double)iv.getWidth()));
   int projectedY = (int)((double)y * ((double)bm.getHeight()/(double)iv.getHeight()));

   //clear canvasDrawingPane
   canvasDrawingPane.drawColor(Color.TRANSPARENT, Mode.CLEAR);
   
   Paint paint = new Paint();
            paint.setStyle(Paint.Style.STROKE);
            paint.setColor(Color.WHITE);
            paint.setStrokeWidth(3);
   canvasDrawingPane.drawRect(startPt.x, startPt.y, projectedX, projectedY, paint);
   imageDrawingPane.invalidate();
   
   
   textSource.setText(x + ":" + y + "/" + iv.getWidth() + " : " + iv.getHeight() + "\n" +
     projectedX + " : " + projectedY + "/" + bm.getWidth() + " : " + bm.getHeight()
     );
  }
 }
 
 private void finalizeDrawing(){
  canvasMaster.drawBitmap(bitmapDrawingPane, 0, 0, null);
 }

 @Override
 protected void onActivityResult(int requestCode, int resultCode, Intent data) {
  super.onActivityResult(requestCode, resultCode, data);
  
  Bitmap tempBitmap;
  
  if(resultCode == RESULT_OK){
   switch (requestCode){
   case RQS_IMAGE1:
    source = data.getData();
    textSource.setText(source.toString());
    
    try {
     //tempBitmap is Immutable bitmap,
     //cannot be passed to Canvas constructor
     tempBitmap = BitmapFactory.decodeStream(
       getContentResolver().openInputStream(source));
     
     Config config;
     if(tempBitmap.getConfig() != null){
      config = tempBitmap.getConfig();
     }else{
      config = Config.ARGB_8888;
     }
     
     //bitmapMaster is Mutable bitmap
     bitmapMaster = Bitmap.createBitmap(
       tempBitmap.getWidth(),
       tempBitmap.getHeight(),
       config);
     
     canvasMaster = new Canvas(bitmapMaster);
     canvasMaster.drawBitmap(tempBitmap, 0, 0, null);
     
     imageResult.setImageBitmap(bitmapMaster);
     
     //Create bitmap of same size for drawing
     bitmapDrawingPane = Bitmap.createBitmap(
       tempBitmap.getWidth(),
       tempBitmap.getHeight(),
       config);
     canvasDrawingPane = new Canvas(bitmapDrawingPane);
     imageDrawingPane.setImageBitmap(bitmapDrawingPane);
     
     
    } catch (FileNotFoundException e) {
     // TODO Auto-generated catch block
     e.printStackTrace();
    }
    
    break;
   }
  }
 }

}


<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"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity" >

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:autoLink="web"
        android:text="http://android-er.blogspot.com/"
        android:textStyle="bold" />

    <Button
        android:id="@+id/loadimage"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Load Image 1" />

    <TextView
        android:id="@+id/sourceuri"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent" >

        <ImageView
            android:id="@+id/result"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:adjustViewBounds="true"
            android:background="@android:color/background_dark"
            android:scaleType="centerInside" />
        <ImageView 
            android:id="@+id/drawingpane"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:adjustViewBounds="true"
            android:scaleType="centerInside"
            android:layout_alignLeft="@id/result"
            android:layout_alignTop="@id/result"
            android:layout_alignRight="@id/result"
            android:layout_alignBottom="@id/result"/>
    </RelativeLayout>

</LinearLayout>


download filesDownload the files.

Correction: To make sure bitmapDrawingPane have alpha channel, create it with Config.ARGB_8888.

     //Create bitmap of same size for drawing
     bitmapDrawingPane = Bitmap.createBitmap(
       tempBitmap.getWidth(),
       tempBitmap.getHeight(),
       Config.ARGB_8888);



more: Something about processing images in Android