Windows Phone: Image Crop With Rectangle

Introduction

Especially for photo apps, we may need to crop the image with a rectangle. That is a little bit difficult to implement using the code. However I will explain very clearly in this article using WriteableBitmap.

Requirements

This sample is targeted to the Windows Phone 7.1 OS.

Description

In this sample, I cropped the image with a rectangle and then saved it to "MedialLibrary". So let's start the development by the following procedure.

Step 1

  • Open Visual Studio.
  • Create a new project named for example "ImageCropWithRect".

Step 2

Open MainPage.xaml and add the following XMAL code.

XAML

  1. <Grid x:Name="LayoutRoot" Background="White">   
  2.         <Grid.RowDefinitions>   
  3.             <RowDefinition Height="Auto"/>   
  4.             <RowDefinition Height="*"/>   
  5.         </Grid.RowDefinitions>   
  6.         <!--ContentPanel - place additional content here-->   
  7.         <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0"></Grid>   
  8.         <StackPanel Orientation="Vertical">   
  9.             <TextBlock HorizontalAlignment="Center" FontSize="30" Text="Image Crop with Recatngle" Foreground="#FF17CDC4"/>   
  10.             <Rectangle Margin="0,5,0,0" Height="0.5" Fill="#FF17CDC4" />   
  11.             <Canvas Height="300" Margin="5" x:Name="canvas" Width="480">   
  12.                 <!--Original Image-->   
  13.                 <Image Width="470" Stretch="Uniform" Name="OriginalImage" Source="/Assets/Nature1.jpg" MouseLeftButtonDown="OriginalImage_MouseLeftButtonDown" MouseLeftButtonUp="OriginalImage_MouseLeftButtonUp" MouseMove="OriginalImage_MouseMove"/>   
  14.                 <!--Rectangle to be used for Crop Original Image-->   
  15.                 <Rectangle x:Name="rect" StrokeThickness="4" Stroke="#FFEA18A7"></Rectangle>   
  16.             </Canvas>   
  17.             <Button Name="CropBtn" Content="CropImage" Background="#FF3CD3CC" Click="CropBtn_Click" />   
  18.             <!--Cropped Image-->   
  19.             <Image Stretch="None" Name="FinalCroppedImage"/>   
  20.             <Button Name="SaveBtn" Visibility="Collapsed" Content="Save to Gallery" Background="#FF3CD3CC" Click="SaveBtn_Click" />   
  21.         </StackPanel>   
  22.     </Grid>  
In the code above in the Canvas layout I added two child controls (OriginalImage and rect). Here "rect" is used for cropping the "OriginalImage" with a rectangle shape. So when we click "CropBtn", the selected rectangle area of the original image source will be set to "FinalCroppedImage". And the cropped image will be saved to the media library when you click on "SaveBtn". You will be able to understand the code above by proceeding to the further important steps.

Step 3

To crop the image, we need the (x, y) co-ordinates and the height and width of the cropped image. On the MouseEvents of "OriginalImage" get the Poin1 and Point2 values to crop the image with a rectangle.

C# Code
  1. //Mouse Move   
  2. private void OriginalImage_MouseMove(object sender, MouseEventArgs e)   
  3. {   
  4.    Point2 = e.GetPosition(OriginalImage);   
  5. }   
  6. //Mouse Up   
  7. private void OriginalImage_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)   
  8. {   
  9.    Point2 = e.GetPosition(OriginalImage);   
  10. }   
  11. //Mouse Down   
  12. private void OriginalImage_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)   
  13. {   
  14.    Point1 = e.GetPosition(OriginalImage);//Set first touchable coordinates as point1   
  15.    Point2 = Point1;   
  16.    rect.Visibility = Visibility.Visible;   
  17. }  
And draw the dynamic rectangle on the mouse move of "OriginalImage".

C# Code
  1. Point Point1, Point2;   
  2.   
  3. public MainPage()   
  4. {   
  5.    InitializeComponent();   
  6.    //fire when render frame   
  7.    CompositionTarget.Rendering += new EventHandler(CompositionTarget_Rendering);   
  8. }   
  9. private void CompositionTarget_Rendering(object sender, EventArgs e)   
  10. {   
  11.    //Used for rendering the cropping rectangle on the image.   
  12.    rect.SetValue(Canvas.LeftProperty, (Point1.X < Point2.X) ? Point1.X : Point2.X);   
  13.    rect.SetValue(Canvas.TopProperty, (Point1.Y < Point2.Y) ? Point1.Y : Point2.Y);   
  14.    rect.Width = (int)Math.Abs(Point2.X - Point1.X);   
  15.    rect.Height = (int)Math.Abs(Point2.Y - Point1.Y);   
  16. }  
Step 4

Be sure to set "WriteableBitmap" with the OrgianlImage on PageLoad.

C# Code
  1. WriteableBitmap WB_CapturedImage;//for original image   
  2. WriteableBitmap WB_CroppedImage;//for cropped image   
  3. public MainPage()   
  4. {   
  5.    InitializeComponent();   
  6.    //fire when render frame   
  7.    CompositionTarget.Rendering += new EventHandler(CompositionTarget_Rendering);   
  8.    this.Loaded+=MainPage_Loaded;   
  9. }   
  10. private void MainPage_Loaded(object sender, RoutedEventArgs e)   
  11. {   
  12.    //Set WriteableBitmap with OrgianlImage   
  13.    WB_CapturedImage = new WriteableBitmap(OriginalImage, null);   
  14. }  
Step 5

Get the cropped image area when "CropBtn" is clicked and set it to "FinalCroppedImage".

C# Code 
  1. private void CropBtn_Click(object sender, RoutedEventArgs e)   
  2. {   
  3.    // Get the size of the source image   
  4.    double originalImageWidth = WB_CapturedImage.PixelWidth;   
  5.    double originalImageHeight = WB_CapturedImage.PixelHeight;   
  6.   
  7.    // Get the size of the image when it is displayed on the phone   
  8.    double displayedWidth = OriginalImage.ActualWidth;   
  9.    double displayedHeight = OriginalImage.ActualHeight;   
  10.   
  11.    // Calculate the ratio of the original image to the displayed image   
  12.    double widthRatio = originalImageWidth / displayedWidth;   
  13.    double heightRatio = originalImageHeight / displayedHeight;   
  14.   
  15.    // Create a new WriteableBitmap. The size of the bitmap is the size of the cropping rectangle   
  16.    // drawn by the user, multiplied by the image size ratio.   
  17.    WB_CroppedImage = new WriteableBitmap((int)(widthRatio * Math.Abs(Point2.X - Point1.X)), (int)
  18.    (heightRatio * Math.Abs(Point2.Y - Point1.Y)));   
  19.   
  20.    // Calculate the offset of the cropped image. This is the distance, in pixels, to the top left corner   
  21.    // of the cropping rectangle, multiplied by the image size ratio.   
  22.    int xoffset = (int)(((Point1.X < Point2.X) ? Point1.X : Point2.X) * widthRatio);   
  23.    int yoffset = (int)(((Point1.Y < Point2.Y) ? Point1.Y : Point2.X) * heightRatio);   
  24.   
  25.    // Copy the pixels from the targeted region of the source image into the target image,   
  26.    // using the calculated offset   
  27.    if (WB_CroppedImage.Pixels.Length > 0)   
  28.    {   
  29.       for (int i = 0; i < WB_CroppedImage.Pixels.Length; i++)   
  30.       {   
  31.          int x = (int)((i % WB_CroppedImage.PixelWidth) + xoffset);   
  32.          int y = (int)((i / WB_CroppedImage.PixelWidth) + yoffset);   
  33.          WB_CroppedImage.Pixels[i] = WB_CapturedImage.Pixels[y * WB_CapturedImage.PixelWidth + x];   
  34.       }   
  35.   
  36.       // Set the source of the image control to the new cropped image   
  37.       FinalCroppedImage.Source = WB_CroppedImage;   
  38.       SaveBtn.Visibility = Visibility.Visible;   
  39.   
  40.    }   
  41.    else   
  42.    {   
  43.       FinalCroppedImage.Source = null;   
  44.       SaveBtn.Visibility = Visibility.Collapsed;   
  45.    }   
  46.    //rect.Visibility = Visibility.Collapsed;   
  47. }  
Step 6

Finally save the cropped image to the MediaLibary when we click on "SaveBtn".

C# Code
  1. private void SaveBtn_Click(object sender, RoutedEventArgs e)   
  2. {   
  3.    try   
  4.    {   
  5.       String tempJPEG = "CroppedImage.jpg";   
  6.       //Create virtual store and file stream. Check for duplicate tempJPEG files.   
  7.       var myStore = IsolatedStorageFile.GetUserStoreForApplication();   
  8.       if (myStore.FileExists(tempJPEG))   
  9.       {   
  10.          myStore.DeleteFile(tempJPEG);   
  11.       }   
  12.       IsolatedStorageFileStream myFileStream = myStore.CreateFile(tempJPEG);   
  13.       //Encode the WriteableBitmap into JPEG stream and place into isolated storage.   
  14.       Extensions.SaveJpeg(WB_CroppedImage, myFileStream, WB_CroppedImage.PixelWidth, WB_CroppedImage.PixelHeight, 0, 85);   
  15.       myFileStream.Close();   
  16.       //Create a new file stream.   
  17.       myFileStream = myStore.OpenFile(tempJPEG, FileMode.Open, FileAccess.Read);   
  18.   
  19.       //Add the JPEG file to the photos library on the device.   
  20.       MediaLibrary library = new MediaLibrary();   
  21.       Picture pic = library.SavePicture("SavedPicture.jpg", myFileStream);   
  22.       MessageBox.Show("Cropped image saved successfully to media library!");   
  23.       myFileStream.Close();   
  24.    }   
  25.    catch   
  26.    {   
  27.       MessageBox.Show("Error on image saving!");   
  28.    }   
  29. }  
Note: 
  1. You need to add a reference to the Microsoft.Xna.Framework in the references of your project.

  2. Ensure you have the ID_CAP_MEDIALIB turned on in your WMAppManifest.xml file.

Result

image crop with recatngle

image crop

saved picture

Summary

From this article we have learned how to crop an image with a rectangle in Windows Phone.

This article is also available at my original blog: link.


Similar Articles