Recipe Loading an Image for Manipulation

This recipe shows an example of an image cut into four pieces and scrambled before being displayed to the screen. It also shows how to create a selectable list of images.

When a picture is taken on the device, it is put in the DCIM/Camera/ directory, which is used as an example image directory in this recipe. The image directory is passed to the ListFiles activity, which lists all files and returns the one chosen by the user.

The chosen picture is then loaded into memory for manipulation. If the file is too large, it can be subsampled as it is loaded to save memory; just replace the single bolded statement in onActivityResult with the following:

BitmapFactory.Options options = new BitmapFactory.Options(); options.inSampleSize = 4;

Bitmap ImageToChange= BitmapFactory.decodeFile(tmp, options);

An inSampleSize of four creates an image 1/16th the size of the original (four times smaller in each of the pixel dimensions).The limit can be adaptive based on the original image size.

Another method to save memory is to resize the bitmap in memory before manipula-tions.This is done using the createScaledBitmap() method, as shown in this recipe. Listing 6.1 shows the main activity.

Listing 6.1 src/com/cookbook/image_manip/ImageManipulation.java package com.cookbook.image_manip;

import android.app.Activity; import android.content.Intent; import android.graphics.Bitmap; import android.graphics.BitmapFactory;

import android.os.Bundle; import android.os.Environment; import android.widget.ImageView;

public class ImageManipulation extends Activity {

static final String CAMERA_PIC_DIR = "/DCIM/Camera/";

ImageView iv;

^Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); iv = (ImageView) findViewById(R.id.my_image);

String ImageDir = Environment.getExternalStorageDirectory() •getAbsolutePath() + CAMERA_PIC_DIR;

Intent i = new Intent(this, ListFiles.class); i.putExtra("directory", ImageDir); startActivityForResult(i,0);

^Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if(requestCode == 0 && resultCode==RESULT_OK) {

String tmp = data.getExtras().getString("clickedFile"); Bitmap ImageToChange= BitmapFactory.decodeFile(tmp); process_image(ImageToChange);

void process_image(Bitmap image) {

Bitmap bm = Bitmap.createScaledBitmap(image, 480, 320, false);

int width = bm.getWidth(); int height = bm.getHeight(); int x= width>>1; int y= height>>1;

int[] pixels1 = new int[(width*height)]; int[] pixels2 = new int[(width*height)]; int[] pixels3 = new int[(width*height)]; int[] pixels4 = new int[(width*height)];

bm.getPixels(pixels1, 0, width, 0, 0, width>>1, height>>1); bm.getPixels(pixels2, 0, width, x, 0, width>>1, height>>1); bm.getPixels(pixels3, 0, width, 0, y, width>>1, height>>1); bm.getPixels(pixels4, 0, width, x, y, width>>1, height>>1); if(bm.isMutable()) {

bm.setPixels(pixels2, 0, width, 0, 0, width>>1, height>>1); bm.setPixels(pixels4, 0, width, x, 0, width>>1, height>>1); bm.setPixels(pixels1, 0, width, 0, y, width>>1, height>>1); bm.setPixels(pixels3, 0, width, x, y, width>>1, height>>1);

iv.setImageBitmap(bm);

The associated main layout is shown in Listing 6.2.

Listing 6.2 res/layout/main.xml

<?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"> <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:textSize="30sp" android:text="Scrambled Picture" /> <ImageView android:id="@+id/my_image" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </LinearLayout>

The secondary activity to list the files in a given directory is shown in Listing 6.3.A File object is created based on the directory String passed to the activity. If it is a directory, the files are sorted into reverse chronological order by specifying a new compare() method based on the lastModified() flag of the files.

If instead an alphabetical list is desired, the sort() method can be used. (This is in the ListFiles activity, too, but commented out.) The list is then built and displayed on the screen using a separate layout file R.layout.file_row, which is shown in Listing 6.4.

Listing 6.3 src/com/cookbook/image_manip/ListFiles.java package com.cookbook.image_manip;

import java.io.File; import java.util.ArrayList; import java.util.Arrays; import java.util.Comparator; import java.util.List;

import android.app.ListActivity;

import android.content.Intent; import android.os.Bundle; import android.view.View; import android.widget.ArrayAdapter; import android.widget.ListView;

public class ListFiles extends ListActivity {

private List<String> directoryEntries = new ArrayList<String>();

@Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Intent i = getIntent();

File directory = new File(i.getStringExtra("directory"));

if (directory.isDirectory()){

File[] files = directory.listFiles();

//sort in descending date order Arrays.sort(files, new Comparator<File>(){ public int compare(File f1, File f2) {

return -Long.valueOf(f1.lastModified()) .compareTo(f2.lastModified());

//fill list with files this.directoryEntries.clear(); for (File file : files){

this.directoryEntries.add(file.getPath());

ArrayAdapter<String> directoryList

= new ArrayAdapter<String>(this,

R.layout.file_row, this.directoryEntries);

//alphabetize entries

//directoryList.sort(null);

this.setListAdapter(directoryList);

^Override protected void onListItemClick(ListView l, View v, int pos, long id) { File clickedFile = new File(this.directoryEntries.get(pos)); Intent i = getIntent();

i.putExtra("clickedFile", clickedFile.toString());

setResult(RESULT_OK, i);

The associated layout file for the ListFiles activity is shown in Listing 6.4.The AndroidManifest XML file must declare both the activities, as shown in Listing 6.5.An example of the output is shown in Figure 6.1.

Listing 6.4 res/layout/file_row.xml

<?xml version="1.0" encoding="utf-8"?> <TextView xmlns:android="http://schemas.android.com/apk/res/android"

android:layout_width="fill_parent"

android:layout_height="wrap_content"

android:textSize="20sp"

android:padding="3pt"

Listing 6.5 AndroidManifest.xml

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

<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.cookbook.image_manip" android:versionCode="1" android:versionName="1.0"> <application android:icon="@drawable/icon"

android:label="@string/app_name"> <activity android:name=".ImageManipulation"

android:label="@string/app_name"> <intent-filter>

<action android:name="android.intent.action. MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <activity android:name=".ListFiles"

android:screenOrientation="portrait" android:label="Choose a File"> <intent-filter>

<action android:name="android.intent.action. VIEW" /> <category android:name="android.intent.category. DEFAULT" /> </intent-filter> </activity> </application>

<uses-sdk android:minSdkVersion="5" /> </manifest>

Figure 6.1 Example of the Android image getting scrambled.
Character Building Thought Power

Character Building Thought Power

Character-Building Thought Power by Ralph Waldo Trine. Ralph draws a distinct line between bad and good habits. In this book, every effort is made by the writer to explain what comprises good habits and why every one needs it early in life. It draws the conclusion that habits nurtured in early life concretize into impulses in future for the good or bad of the subject.

Get My Free Ebook


Post a comment