All image processing projects have one thing in common: an image (or multiple images). We need to first acquire an image, then we need to get it into a format that is conducive to editing. Let’s get cracking.
Setting up the Project
We are going to set up a very simple project to show the original image, the processed image, and an application bar button to start the image capture. This will be the basis for future projects.
1.) Create a new Silverlight for Windows Phone Project
2.) Modify the LayoutRoot to have two images:
<Grid x:Name="LayoutRoot"
Background="Transparent">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Image x:Name="OriginalImage"
Grid.Row="0" />
<Image x:Name="ProcessedImage"
Grid.Row="1" />
</Grid>
3.) Create the application bar:
<phone:PhoneApplicationPage.ApplicationBar>
<shell:ApplicationBar IsVisible="True" >
<shell:ApplicationBarIconButton
x:Name="AcquireImageButton"
IconUri="/Images/appbar.feature.camera.rest.png"
Text="acquire"
Click="AcquireImageButton_Click" />
</shell:ApplicationBar>
</phone:PhoneApplicationPage.ApplicationBar>
Note: Windows Phone 7 icons can be found here: C:\Program Files (x86)\Microsoft SDKs\Windows Phone\v7.0\Icons
Acquiring the Image
Now for the meat of the post. First, we need to acquire an image then convert it to a WriteableBitmap. In the wild, we are going to want to actually take a picture, but in the lab we simply want to load an image from the project.
1.) When we press the Acquire button we want to launch the Camera Capture Task. Once it’s complete, we can start processing.
private void AcquireImageButton_Click(object sender, EventArgs e)
{
CameraCaptureTask cct = new CameraCaptureTask();
cct.Completed += new EventHandler<PhotoResult>(cct_Completed);
cct.Show();
}
2.) Create a BitmapImage and a WriteableBitmap from the results.
void cct_Completed(object sender, PhotoResult e)
{
// if we are working with the actual device
// we actually want to take a picture
// otherwise we are going to use a jpg
// I have included in the project
if (Microsoft.Devices.Environment.DeviceType == DeviceType.Device)
{
// TaskResults can be OK, Cancel, or None
// Working with the device here is rather
// painful because it cancels every time
// for me when I’m connected so I have to
// run disconnected from the PC
if (e.TaskResult == TaskResult.OK)
{
BitmapImage bmp = new BitmapImage();
bmp.SetSource(e.ChosenPhoto);
OriginalImage.Source = bmp;
WriteableBitmap processedImage = new WriteableBitmap(bmp);
// you could put some automated processing here
ProcessedImage.Source = processedImage;
}
}
//else we are running from the emulator
//in this case the CameraCaptureTask "works"
//but it doesn’t really return anything of value
//so we are going to use an image added to the
//project
else
{
//Creating a WriteableBitmap from a
//BitmapImage that was created using a
//Uri can be a little tricky.
//If you don’t follow these steps you
//might get a cryptic exception
BitmapImage bmp = new BitmapImage();
//Options here are None, DelayCreation (default), and
//IgnoreImageCache (in Silverlight). Mainly, we don’t want
//DelayCreation because it waits to initialize it until
//necessary (i.e. when it’s shown). Since we are setting
//the source of OriginalBitmap to bmp, we don’t actually
//need to perform this step in this case. In general,
//however, for my projects, I often want to process the
//image before I display it.
bmp.CreateOptions = BitmapCreateOptions.None;
//note how we are waiting for the image to
//finish opening before we try to create the
//WriteableBitmap
bmp.ImageOpened +=
new EventHandler<RoutedEventArgs>(bmp_ImageOpened);
//I added this test image as Content to the Images folder.
//I recommend taking a photo with the phone then adding it
//to your project. This ensures the image will be the correct
//format and consistent dimensions (2592×1944) for processing
bmp.UriSource =
new Uri("Images/test_image.jpg", UriKind.Relative);
OriginalImage.Source = bmp;
}
}
void bmp_ImageOpened(object sender, RoutedEventArgs e)
{
WriteableBitmap processedImage =
new WriteableBitmap(sender as BitmapImage);
// you could put some automated processing here
ProcessedImage.Source = processedImage;
}
3.) Run it
You can really see the HTC HD7 pink color issue in this photo.
Summary
This is a fairly trivial task, but getting the WriteableBitmap functioning properly is the basis for everything from here on out.
Download Code
Up next: Extracting Colors