Blit not producing anticipated results

Mar 3, 2014 at 10:15 PM
I'm using the Blit method for image annotation functionality in a Windows Store app. Essentially the user takes a picture and is able to use the Windows.UI.Input.Inking.InkManager to draw on the picture (e.g. circles, boxes, etc). I'm then using the Blit method to combine the picture the user took with the annotation produced by the InkManager. The problem is that the combined saved image has the mark up from the InkManager appearing horizontally offset.

See https://onedrive.live.com/?cid=c21327df8f57089d#cid=C21327DF8F57089D&id=C21327DF8F57089D%21157 for examples of the original and saved (blitted) image.

The code to save the blitted images:
private async Task SaveMergedImages()
        {
            //Image foreground
            Windows.UI.Xaml.Media.Imaging.WriteableBitmap foregroundBmp;
            using (var a = new InMemoryRandomAccessStream())
            {
                //CurrentManager is a Windows.UI.Input.Inking.InkManager
                await CurrentManager.SaveAsync(a);

                a.Seek(0);
                foregroundBmp = await new Windows.UI.Xaml.Media.Imaging.WriteableBitmap(Convert.ToInt32(CurrentManager.BoundingRect.Width), Convert.ToInt32(CurrentManager.BoundingRect.Height)).FromStream(a);
            }

            Windows.UI.Xaml.Media.Imaging.WriteableBitmap backgroundBmp = null;
            using (var ims = new InMemoryRandomAccessStream())
            {
                using (var dataWriter = new DataWriter(ims))
                {
                    //ViewModel.ImageByteArrayToBeEdited is a byte[] of the image thats going to be edited
                    dataWriter.WriteBytes(ViewModel.ImageByteArrayToBeEdited);
                    await dataWriter.StoreAsync();

                    backgroundBmp = new Windows.UI.Xaml.Media.Imaging.WriteableBitmap(ViewModel.ImageToBeEdited.PixelWidth, ViewModel.ImageToBeEdited.PixelHeight);
                    ims.Seek(0);

                    //set the source of the in memory bmp as blit relies upon the SourceURI
                    await backgroundBmp.SetSourceAsync(ims);
                }
            }

            //merge 'em!
            backgroundBmp.Blit(
                new Rect(CurrentManager.BoundingRect.X, CurrentManager.BoundingRect.Y, foregroundBmp.PixelWidth, foregroundBmp.PixelHeight),
                foregroundBmp,
                new Rect(0, 0, foregroundBmp.PixelWidth, foregroundBmp.PixelHeight),
                WriteableBitmapExtensions.BlendMode.Alpha);

            await backgroundBmp.SaveToFile();
        }
This is all being done on a XAML page that has a Canvas with the canvas Background set to an ImageBrush.
//Windows.UI.Xaml.Controls.Canvas
            InkCanvas.Background = new ImageBrush()
            {
                ImageSource = ViewModel.ImageToBeEdited,
                Stretch = Stretch.Uniform
            };
I've tried various tweaks to the code, including changing the Stretch of the ImageBrush and multiple variations Rect params of the Blit method. None have worked. Please help.
Coordinator
Mar 4, 2014 at 5:02 AM
Looks like the overlay has a different size. It needs to have the same width and height. The Blit does not scale. You can use the Resize method for that.
  • Rene
Mar 4, 2014 at 3:14 PM
Thanks, but according to your post at https://writeablebitmapex.codeplex.com/discussions/455204 you can blit images of different sizes. Is this not the case anymore? Also, can you elaborate on how I could use the Resize method to accomplish what I need?
Coordinator
Mar 4, 2014 at 6:05 PM
Sure you can blit different sizes, but the bitmaps won't be scaled. You need to either resize your target or destination bitmap to be the same size if you want them to overlay 1:1.
  • Rene
Mar 5, 2014 at 7:39 PM
I managed to make this work by adding dummy "pushpins" to 2 diagonal corners of the InkManager to fake the manager into thinking it was the same size as my background. Now the user can mark up an image at will and the foreground (e.g. inkManager) will always be the same size as the background. When blitting the images, the foreground is then not stretched to the size of the background, preserving the scale and precision of the mark up.

Before blitting the images, I call this method:
private void addDummyCornerPins(WriteableBitmap backgroundBmp)
        {
            var windowHeightHalf = Window.Current.Bounds.Height / 2;
            var windowWidthHalf = Window.Current.Bounds.Width / 2;
            var imgHeightHalf = backgroundBmp.PixelHeight / 2;
            var imgWidthHalf = backgroundBmp.PixelWidth / 2;

            var ptListTopLeft = new List<Point>()
            { 
                new Point(windowWidthHalf - imgWidthHalf, windowHeightHalf + imgHeightHalf)
            };

            var ptBottomRight = windowWidthHalf + imgWidthHalf + windowHeightHalf - imgHeightHalf;
            var ptListBottomRight = new List<Point>()
            { 
                new Point(windowWidthHalf + imgWidthHalf, windowHeightHalf - imgHeightHalf)
            };

            var builder = new InkStrokeBuilder();
            var strokeTopLeft = builder.CreateStroke(ptListTopLeft);
            var strokeBottomRight = builder.CreateStroke(ptListBottomRight);

            CurrentInkManager.AddStroke(strokeTopLeft);
            CurrentInkManager.AddStroke(strokeBottomRight);
        }