Introduction:
Especially for photo apps,we may need to crop the image with rectangle which is little bit difficult to implement through the code.However i will explained very clearly in this post with help of WriteableBitmap .Requirements:
This sample is targeted to windowsphone 7.1 OS
Description:
In this sample i was cropped the image with rectangle,and then saved it to 'MedialLibrary'.So lets start the development by following steps.Step 1:
- Open Visual Studio
- Create new project name(Ex: "ImageCropWithRect")
Open MainPage.xaml and add following xaml code.
XAML
<Grid x:Name="LayoutRoot" Background="White"> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition Height="*"/> </Grid.RowDefinitions> <!--ContentPanel - place additional content here--> <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0"></Grid> <StackPanel Orientation="Vertical"> <TextBlock HorizontalAlignment="Center" FontSize="30" Text="Image Crop with Recatngle" Foreground="#FF17CDC4"/> <Rectangle Margin="0,5,0,0" Height="0.5" Fill="#FF17CDC4" /> <Canvas Height="300" Margin="5" x:Name="canvas" Width="480"> <!--Original Image--> <Image Width="470" Stretch="Uniform" Name="OriginalImage" Source="/Assets/Nature1.jpg" MouseLeftButtonDown="OriginalImage_MouseLeftButtonDown" MouseLeftButtonUp="OriginalImage_MouseLeftButtonUp" MouseMove="OriginalImage_MouseMove"/> <!--Rectangle to be used for Crop Original Image--> <Rectangle x:Name="rect" StrokeThickness="4" Stroke="#FFEA18A7"></Rectangle> </Canvas> <Button Name="CropBtn" Content="CropImage" Background="#FF3CD3CC" Click="CropBtn_Click" /> <!--Cropped Image--> <Image Stretch="None" Name="FinalCroppedImage"/> <Button Name="SaveBtn" Visibility="Collapsed" Content="Save to Gallery" Background="#FF3CD3CC" Click="SaveBtn_Click" /> </StackPanel> </Grid>
In above code In Canvas layout I added two child controls(OriginalImage,rect).Here 'rect' is used for crop the 'OriginalImage' with rectangle shape.So when click the 'CropBtn' ,selected rectangle area of OriginalImage source will be set to 'FinalCroppedImage'.And cropped image will be saved to media library when you click on 'SaveBtn' .However you will be understand the above code by moving to further important steps.
Step 2:
To crop image ,we need to (x, y) co-ordinates and the height & width of the cropped image.On MouseEvents of 'OriginalImage' get the Poin1,Point2 values to make image crop with rectangle shape.
C#
//Mouse Move private void OriginalImage_MouseMove(object sender, MouseEventArgs e) { Point2 = e.GetPosition(OriginalImage); } //Mouse Up private void OriginalImage_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) { Point2 = e.GetPosition(OriginalImage); } //Mouse Down private void OriginalImage_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) { Point1 = e.GetPosition(OriginalImage);//Set first touchable coordinates as point1 Point2 = Point1; rect.Visibility = Visibility.Visible; }
And draw the dynamic rectangle on mouse move of 'OriginalImage'
C#
Point Point1, Point2; public MainPage() { InitializeComponent(); //fire when render frame CompositionTarget.Rendering += new EventHandler(CompositionTarget_Rendering); } private void CompositionTarget_Rendering(object sender, EventArgs e) { //Used for rendering the cropping rectangle on the image. rect.SetValue(Canvas.LeftProperty, (Point1.X < Point2.X) ? Point1.X : Point2.X); rect.SetValue(Canvas.TopProperty, (Point1.Y < Point2.Y) ? Point1.Y : Point2.Y); rect.Width = (int)Math.Abs(Point2.X - Point1.X); rect.Height = (int)Math.Abs(Point2.Y - Point1.Y); }
Step 3:
Make sure to set 'WriteableBitmap' with OrgianlImage on PageLoad.
C#
WriteableBitmap WB_CapturedImage;//for original image WriteableBitmap WB_CroppedImage;//for cropped image public MainPage() { InitializeComponent(); //fire when render frame CompositionTarget.Rendering += new EventHandler(CompositionTarget_Rendering); this.Loaded+=MainPage_Loaded; } private void MainPage_Loaded(object sender, RoutedEventArgs e) { //Set WriteableBitmap with OrgianlImage WB_CapturedImage = new WriteableBitmap(OriginalImage, null); }
Step 4:
Get the cropped image area when click on 'CropBtn' and set it to 'FinalCroppedImage'.
C#
private void CropBtn_Click(object sender, RoutedEventArgs e) { // Get the size of the source image double originalImageWidth = WB_CapturedImage.PixelWidth; double originalImageHeight = WB_CapturedImage.PixelHeight; // Get the size of the image when it is displayed on the phone double displayedWidth = OriginalImage.ActualWidth; double displayedHeight = OriginalImage.ActualHeight; // Calculate the ratio of the original image to the displayed image double widthRatio = originalImageWidth / displayedWidth; double heightRatio = originalImageHeight / displayedHeight; // Create a new WriteableBitmap. The size of the bitmap is the size of the cropping rectangle // drawn by the user, multiplied by the image size ratio. WB_CroppedImage = new WriteableBitmap((int)(widthRatio * Math.Abs(Point2.X - Point1.X)), (int)(heightRatio * Math.Abs(Point2.Y - Point1.Y))); // Calculate the offset of the cropped image. This is the distance, in pixels, to the top left corner // of the cropping rectangle, multiplied by the image size ratio. int xoffset = (int)(((Point1.X < Point2.X) ? Point1.X : Point2.X) * widthRatio); int yoffset = (int)(((Point1.Y < Point2.Y) ? Point1.Y : Point2.X) * heightRatio); // Copy the pixels from the targeted region of the source image into the target image, // using the calculated offset if (WB_CroppedImage.Pixels.Length > 0) { for (int i = 0; i < WB_CroppedImage.Pixels.Length; i++) { int x = (int)((i % WB_CroppedImage.PixelWidth) + xoffset); int y = (int)((i / WB_CroppedImage.PixelWidth) + yoffset); WB_CroppedImage.Pixels[i] = WB_CapturedImage.Pixels[y * WB_CapturedImage.PixelWidth + x]; } // Set the source of the image control to the new cropped image FinalCroppedImage.Source = WB_CroppedImage; SaveBtn.Visibility = Visibility.Visible; } else { FinalCroppedImage.Source = null; SaveBtn.Visibility = Visibility.Collapsed; } //rect.Visibility = Visibility.Collapsed; }
Step 5:
Finally save cropped image to MediaLibary when click on 'SaveBtn'.
C#
private void SaveBtn_Click(object sender, RoutedEventArgs e) { try { String tempJPEG = "CroppedImage.jpg"; //Create virtual store and file stream. Check for duplicate tempJPEG files. var myStore = IsolatedStorageFile.GetUserStoreForApplication(); if (myStore.FileExists(tempJPEG)) { myStore.DeleteFile(tempJPEG); } IsolatedStorageFileStream myFileStream = myStore.CreateFile(tempJPEG); //Encode the WriteableBitmap into JPEG stream and place into isolated storage. Extensions.SaveJpeg(WB_CroppedImage, myFileStream, WB_CroppedImage.PixelWidth, WB_CroppedImage.PixelHeight, 0, 85); myFileStream.Close(); //Create a new file stream. myFileStream = myStore.OpenFile(tempJPEG, FileMode.Open, FileAccess.Read); //Add the JPEG file to the photos library on the device. MediaLibrary library = new MediaLibrary(); Picture pic = library.SavePicture("SavedPicture.jpg", myFileStream); MessageBox.Show("Cropped image saved successfully to media library!"); myFileStream.Close(); } catch { MessageBox.Show("Error on image saving!"); } }
Note:
1)You need to add a reference to the Microsoft.Xna.Framework in the references of your project.
2)Make sure you have the ID_CAP_MEDIALIB turned on in your WMAppManifest.xml file.
Result:
Follow me always at @Subramanyam_B
Have a nice day by Subramanyam Raju :)
Follow me always at @Subramanyam_B
Have a nice day by Subramanyam Raju :)
plaz can download the code
ReplyDeletenice..and great..
ReplyDeletebut can you show some example..crop an image with perspektif correction and interpolation with C#...
im very2 gracaeful for your concern...
can you please tell me how to drag the rectangle for above example. Suppose i selected some part for editing. now i want to drag that rectangle. how to do this?
ReplyDeleteWindows Phone 8.1? Don't you just hate Microsoft? You go and learn all this hard stuff and then they go and screw it up and change it all. Damn them!
ReplyDeleteHi I am working on windows phone 8.1 in this Mouseup, mousedown events not there in windows 8.1 can you help how it will work windows phone 8.1
ReplyDelete