Drawing on Existing Images

Since we are drawing on a Canvas, we can use techniques described in the previous chapter to draw an image to the Canvas and then draw on top of that image.

Let's go through a full example.

package com.apress.proandroidmedia.ch4.choosepicturedraw;

import java.io.FileNotFoundException;

import android.app.Activity; import android.content.Intent; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Matrix; import android.graphics.Paint; import android.net.Uri; import android.os.Bundle; import android.util.Log; import android.view.Display; 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;

Our activity will implement both OnClickListener and OnTouchListener. The OnClickListener is so that our activity can respond to a Button press. The OnTouchListener is so that we can draw on the ImageView using the touchscreen.

public class ChoosePictureDraw extends Activity implements OnClickListener,~ OnTouchListener {

We have two main UI elements. The first one is the ImageView, which will display our Bitmap, which we'll draw onto. The second is a Button that the user will press to select an image from the Gallery application.

ImageView choosenImageView; Button choosePicture;

We need to have two Bitmap objects. The first is the one that contains the scaled version of the selected image. The second is the mutable version that we'll draw the first one into and draw on top of.

Bitmap bmp; Bitmap alteredBitmap; Canvas canvas; Paint paint; Matrix matrix;

^Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main);

choosenImageView = (ImageView) this.findViewById(R.id.ChoosenImageView); choosePicture = (Button) this.findViewById(R.id.ChoosePictureButton);

After we obtain references to the ImageView and Button, we set the listener for each of the events, OnClick and OnTouch, to be our activity.

choosePicture.setOnClickListener(this); choosenImageView.setOnTouchListener(this);

Our onClick method follows. This uses the standard intent to allow the user to pick an image from the Gallery application.

public void onClick(View v) {

Intent choosePictureIntent = new Intent( Intent.ACTIONJPICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_JRI); startActivityForResult(choosePictureIntent, 0);

Our onActivityResult method is called after the user selects the image. It loads the image selected into a Bitmap that is scaled to the size of the screen.

protected void onActivityResult(int requestCode, int resultCode, Intent intent) {

super.onActivityResult(requestCode, resultCode, intent);

Uri imageFileUri = intent.getData();

Display currentDisplay = getWindowManager().getDefaultDisplay();

float dw = currentDisplay.getWidth(); float dh = currentDisplay.getHeight();

BitmapFactory.Options bmpFactoryOptions = new BitmapFactory.Options(); bmpFactoryOptions.inJustDecodeBounds = true; bmp = BitmapFactory.decodeStream(

getContentResolver().openInputStream(imageFileUri), null, bmpFactoryOptions);

int heightRatio = (int)Math.ceil(bmpFactoryOptions.outHeight/dh); int widthRatio = (int)Math.ceil(bmpFactoryOptions.outWidth/dw); if (heightRatio > 1 && widthRatio > 1) { if (heightRatio > widthRatio) {

bmpFactoryOptions.inSampleSize = heightRatio;

// Width ratio is larger, scale according to it bmpFactoryOptions.inSampleSize = widthRatio;

bmpFactoryOptions.inJustDecodeBounds = false; bmp = BitmapFactory.decodeStream(

getContentResolver().openInputStream(imageFileUri), null, bmpFactoryOptions);

After the Bitmap is loaded, we create a mutable Bitmap, alteredBitmap, and draw our first Bitmap into it.

alteredBitmap = Bitmap.createBitmap(

bmp.getWidth(),bmp.getHeight(),bmp.getConfig()); canvas = new Canvas(alteredBitmap); paint = new Paint(); paint.setColor(Color.GREEN); paint.setStrokeWidth(5); matrix = new Matrix(); canvas.drawBitmap(bmp, matrix, paint);

choosenImageView.setImageBitmap(alteredBitmap); choosenImageView.setOnTouchListener(this);

catch (FileNotFoundException e) { Log.v("ERROR",e.toString());

Now we simply implement our onTouch method in the same manner as we did before. Instead of drawing on an empty Bitmap Canvas, we are now drawing over the top of an existing image.

float downx = 0; float downy = 0; float upx = 0; float upy = 0;

public boolean onTouch(View v, MotionEvent event) { int action = event.getAction(); switch (action) {

case MotionEvent.ACTION_DOWN: downx = event.getX(); downy = event.getY(); break;

case MotionEvent.ACTION_MOVE: upx = event.getX(); upy = event.getY();

canvas.drawLine(downx, downy, upx, upy, paint);

choosenImageView.invalidate();

break;

case MotionEvent.ACTION_UP: upx = event.getX(); upy = event.getY();

canvas.drawLine(downx, downy, upx, upy, paint);

choosenImageView.invalidate();

break;

case MotionEvent.ACTION_CANCEL:

break; default: break;

return true;

What follows is the layout XML file for the foregoing activity. It specifies the ImageView and the Button in a standard LinearLayout.

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent"

android:layout_height="fill_parent" >

<Button android:layout_width="fill_parent" android:layout_height="wrap_content"

android:text="Choose Picture" android:id="@+id/ChoosePictureButton"/> <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/ChoosenImageView"> </ImageView> </LinearLayout>

Figure 4-18. Drawing on an existing image
0 0

Post a comment