title: Manipulating image (translate + scale) and then crop the image in Universal App?
body: <p>After 2 frustrating days of trying to build an image cropper control I turn to StackOverflow to find an answer.</p>
  
  <p>I'm porting my WP8.0 (Silverlight) app to WinRT (Universal app for WP8.1 and W8.1), and I got everything covered... Except the page where the user selects an image from the picture library and it get's loaded on the page. The user can then move the image around, or zoom in. There is a white rectangle border that is the cropper rectangle (864px 605px - this should also be the output).</p>
  
  <p>What is the best way to do this? The images that get's loaded are higher in resolutions, so my guess would be recalculating the on screen pixels to the image pixels. This code works fine for translating, but when the image gets scaled there is weird offset:</p>
  
  <p><strong>XAML:</strong>
      </p>
  
  <pre><code>&lt;Path x:Name="SelectionPath" Stroke="Red" StrokeThickness="3" /&gt;
  </code></pre>
  
  <p><strong>C#</strong>:</p>
  
  <pre><code>public async void SetImage(StorageFile selectedFile)
      {
          Photo.ManipulationDelta += Composite_ManipulationDelta;
          compositeTranslation = new CompositeTransform();
          Photo.RenderTransform = this.compositeTranslation;
          Photo.ManipulationMode = ManipulationModes.TranslateX | ManipulationModes.TranslateY | ManipulationModes.Scale | ManipulationModes.Rotate;
          storageFile = selectedFile;
  
  
  
          storageFile = selectedFile;
          IRandomAccessStream inputStream = await selectedFile.OpenAsync(FileAccessMode.Read);
  
         var properties = await storageFile.Properties.GetImagePropertiesAsync();
         ImgWidth = properties.Width;
  
  
          BitmapImage tempImage = new BitmapImage();
  
          tempImage.SetSource(inputStream);
          Photo.Source = tempImage;
      }
  
      void Composite_ManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs e)
      {
          // scale the image.
          compositeTranslation.CenterX = Photo.ActualWidth / 2;
          compositeTranslation.CenterY = Photo.ActualHeight / 2;
          compositeTranslation.ScaleX *= e.Delta.Scale;
          compositeTranslation.ScaleY *= e.Delta.Scale;
          compositeTranslation.TranslateX += e.Delta.Translation.X;
          compositeTranslation.TranslateY += e.Delta.Translation.Y;
  
  
          GeneralTransform transform = Photo.TransformToVisual(LayoutRoot);
          Point controlPosition = transform.TransformPoint(new Point(0, 0));
  
          int pointX = (int)controlPosition.X;
          int pointY = (int)controlPosition.Y;
  
  
  
      }
  public async Task CropImage()
      {
  
          IBuffer data = await FileIO.ReadBufferAsync(storageFile);
  
          // create a stream from the file
          InMemoryRandomAccessStream ms = new InMemoryRandomAccessStream();
          DataWriter dw = new DataWriter(ms);
          dw.WriteBuffer(data);
          await dw.StoreAsync();
          ms.Seek(0);
  
          // find out how big the image is, don't need this if you already know
          BitmapImage bm = new BitmapImage();
          await bm.SetSourceAsync(ms);
  
          // create a writable bitmap of the right size
          WriteableBitmap wb = new WriteableBitmap(bm.PixelWidth, bm.PixelHeight);
          ms.Seek(0);
  
          // load the writable bitpamp from the stream
          await wb.SetSourceAsync(ms);
  
                 GeneralTransform transform = Photo.TransformToVisual(LayoutRoot);
          Point controlPosition = transform.TransformPoint(new Point(0, 0));
          int pointX = (int)controlPosition.X;
          int pointY = (int)controlPosition.Y;
  
          int CropPosX = 0 - pointX;
          int CropPosY = 0 - pointY;
  
          int UIXPos = (int)Math.Round(CropPosX * compositeTranslation.ScaleX);
          int UIYPos = 413 + (int)Math.Round(CropPosY * compositeTranslation.ScaleY);
  
          double ImgFactor = ImgWidth / Photo.ActualWidth;
          int ImgXPos = (int)Math.Round(UIXPos * ImgFactor);
          int ImgYPos = (int)Math.Round(UIYPos * ImgFactor);
  
          //int CropWidth = 864;
          //int CropHeight = 605;
  
  
  
          int CropWidth = (int)Math.Round(864 * ImgFactor);
          int CropHeight = (int)Math.Round(605 * ImgFactor);
          WriteableBitmap wb2 = wb.Crop(ImgXPos, ImgYPos, CropWidth, CropHeight);
          CroppedImage.Source = wb2;
      }
  </code></pre>
  
  <p>Any pointers are greatly appreciated!</p>
  
  <p><strong>The Lumia Imaging SDK (project: Image Sequencer) has exactly the thing I need, but their sample is based on Silverlight. Stuff like Viewports are not longer supported in WinRT:</strong></p>
  
  <p><a href="http://developer.nokia.com/resources/library/Lumia/nokia-imaging-sdk/sample-projects/image-sequencer.html#toc_Seealso" rel="nofollow">http://developer.nokia.com/resources/library/Lumia/nokia-imaging-sdk/sample-projects/image-sequencer.html#toc_Seealso</a></p>
  
  <p>P.S. Microsoft should really stop messing around with their platforms. Stuff that used to work in the past don't anymore, with no good other options. Super frustrating.</p>