Before we get into the specific mechanisms used to alter the images, let's look at how we can create a new, empty Bitmap
object and draw an existing Bitmap
into that. This is the process that we will be using to create altered versions of our images.
In the foregoing example, we have a Bitmap
object instantiated with an image that has been selected by the user. It has been instantiated by a call to BitmapFactory
's decodeStream
method, as we learned how to do in Chapter 1.
Bitmap bmp = BitmapFactory.decodeStream(getContentResolver().
openInputStream(imageFileUri), null, bmpFactoryOptions);
In order to use this Bitmap
as the source for our image editing experiments, we need to be able to draw this Bitmap
onto the screen with the effects applied. Additionally, it would be great to draw it to an object that we can use to save the resulting image from. It makes sense that we'll want to create an empty Bitmap
object with the same dimensions as this one and use that as the destination for our altered Bitmap
.
This object, alteredBitmap
, is created with the same width, height, and color depth as the source Bitmap
, bmp
. Since we used the Bitmap
class's createBitmap
method with the width, height, and Bitmap.Config
object as parameters, we are obtaining a mutable Bitmap
object in return. Mutable means that we can change the pixel values represented by this Bitmap
. If we had an immutable Bitmap
, we would be unable to draw into it. This method call is one of the only ways to instantiate a mutable Bitmap
object.
The next thing we'll need is a Canvas
object. In Android a Canvas
is, as you would expect, something used to draw on. A Canvas
can be created by passing in a Bitmap
object in its constructor, and subsequently it can be used to draw.
Canvas canvas = new Canvas(alteredBitmap);
Last, we'll need a Paint
object. When we do the actual drawing, the Paint
object comes into play. Specifically, it allows us to alter things such as color and contrast, but we'll get to that later. For now, we are going to use a default Paint
object.
Paint paint = new Paint();
Now we have all of the required components to draw the source Bitmap
into an empty mutable Bitmap
object. Here is all of the code just described put together.
Bitmap bmp = BitmapFactory.decodeStream(getContentResolver().
openInputStream(imageFileUri), null, bmpFactoryOptions);
Bitmap alteredBitmap = Bitmap.createBitmap(bmp.getWidth(),bmp.getHeight(),
bmp.getConfig());
Canvas canvas = new Canvas(alteredBitmap);
Paint paint = new Paint();
canvas.drawBitmap(bmp, 0, 0, paint);
ImageView alteredImageView = (ImageView) this.findViewById(R.id.AlteredImageView);
alteredImageView.setImageBitmap(alteredBitmap);
The drawBitmap
method on the Canvas
object we are using takes the source Bitmap
and an x, y offset along with our Paint
object. This causes our alteredBitmap
object to contain the exact same information as our original bitmap.
We can plug all of this code into our Choose Picture example. It would come near the end of the onActivityResult
method, directly after the bmp = BitmapFactory.decodeStream
line. Be careful not to duplicate that line, as is shown in the foregoing code snippet as well. Also don't forget to add the appropriate import
statements.
Following that, we want to display our alteredBitmap
object. To do that, we are using a standard ImageView
and calling setImageBitmap
with our alteredBitmap
. This assumes that we have an ImageView
with the id AlteredImageView
declared in our Layout XML.
Here is the updated Layout XML for our full Choose Picture example, which contains the original ImageView
as well as our new ImageView
for the alteredBitmap
as shown in Figure 3–4.
<?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/ChosenImageView"></ImageView>
<ImageView android:layout_width="wrap_content" android:layout_height="wrap_content"
android:id="@+id/AlteredImageView"></ImageView>
</LinearLayout>
Figure 3–4. The application after the user has selected an image with the second bitmap object displayed
3.16.76.138