1

I would like to use a FrameworkElement (such as a Panel) as an Image (to use the Nokia Image SDK). I would like to apply an effect not on an image but on a FrameworkElement.

I've been struggling trying to use a FrameworkElement as a writeableBitmap then to a stream for my FilterEffect.

Here is what i have done :

    private async void testCartoon_Tap(object sender, System.Windows.Input.GestureEventArgs e)
    {

       //the panel I want as an Image
       var rootElement = ContentPanel as FrameworkElement; 

       WriteableBitmap myWB = new WriteableBitmap(rootElement,null);

       byte[] bytes =  myWB.ToByteArray();

       MemoryStream stream = new MemoryStream();

       await stream.WriteAsync(myWB.ToByteArray(),0,bytes.Count());

       stream.Seek(0, SeekOrigin.Begin);

       var backgroundSource = new StreamImageSource(stream);

       var filterEffect = new FilterEffect(backgroundSource);

        CartoonFilter cartoonFilter = new CartoonFilter();



        filterEffect.Filters = new[] { cartoonFilter };

        var renderer = new WriteableBitmapRenderer(filterEffect, _cartoonImageBitmap);

        _cartoonImageBitmap = await renderer.RenderAsync();

        ImageCartoon.Source = _cartoonImageBitmap;
  }

The CartoonFilter is one of the NokiaImagingSDK Filter.

I defined my _cartoonImageBitmap like this :

  _cartoonImageBitmap = new WriteableBitmap((int)ImageCartoon.Width, (int)ImageCartoon.Height);

and ImageCartoon in xaml :

   <Image x:Name="ImageCartoon" Width="456" Height="240" Grid.Row="1" ></Image>

I get the exception : "Value doesn't fall within the expected range" at line

     _cartoonImageBitmap = await renderer.RenderAsync();

Do you have any idea why ?

Is there a better way to get a stream out of a FrameworkElement ?

(I know i can save the writeableBitmap into the filestorage before reading it but I would like to avoid saving the image to increase performance).

Thanks a lot for your help.

David Božjak
  • 16,887
  • 18
  • 67
  • 98
Thomas Salandre
  • 817
  • 3
  • 14
  • 27

2 Answers2

0

This is just a hunch, but still. it might be worth a shot. When do you create your _cartoonImageBitmap? It looks like you are doing it in a constructor.

The problem could be that your line _cartoonImageBitmap = new WriteableBitmap((int)ImageCartoon.Width, (int)ImageCartoon.Height); executes before ImageCartoon get's initialized with it's final size. In the constructor it's size should still be (0, 0).

This is the error you would get from Renderer if the destination source would have a size of (0, 0) so I think it is worth trying to create the _cartoonImageBitmap with a static size, for example (500, 500).

Give it a try and report!

David Božjak
  • 16,887
  • 18
  • 67
  • 98
  • Thanks for your help but unfortunately it's not that. I Checked and _cartoonImageBitmap has got a size. I may see two problems : first : byte[] bytes is full of 0. when it should contains other values. Secondly : maybe my WriteAsync is not finish when I try to use the stream. – Thomas Salandre Jan 27 '14 at 09:14
  • Ah, darn. Well since you await the WriteAsync it should complete. I'd focus on why the byte array contains only zeros. Out of curiosity though, what are you trying to achieve? – David Božjak Jan 27 '14 at 10:41
  • Yes it was the writeAsync. I just found the solution, I'm gonna post it. I am trying to apply an effect on a whole panel (such as a blurring effect) so that when I slide a panel on top of another, the one on the back will be progressively blurred. (you can see that on iPhone or Android App). – Thomas Salandre Jan 27 '14 at 10:53
0

I found the solution : the problem came from the WriteAsync method. here is what I've done :

  private async void testCartoon_Tap(object sender, System.Windows.Input.GestureEventArgs e)
{

   //the panel I want as an Image
   var rootElement = ContentPanel as FrameworkElement; 

   WriteableBitmap myWB = new WriteableBitmap((int)rootElement.ActualWidth,    (int)rootElement.ActualHeight);
   myWB.Render(rootElement, new MatrixTransform());
   myWB.Invalidate();


    using (var stream = new MemoryStream())
    {

      myWB.SaveJpeg(stream, myWB.PixelWidth, myWB.PixelHeight, 0, 100);

      stream.Seek(0, SeekOrigin.Begin);

      var backgroundSource = new StreamImageSource(stream);

      var filterEffect = new FilterEffect(backgroundSource);

      CartoonFilter cartoonFilter = new CartoonFilter();

      filterEffect.Filters = new[] { cartoonFilter };

      var renderer = new WriteableBitmapRenderer(filterEffect, _cartoonImageBitmap);

      _cartoonImageBitmap = await renderer.RenderAsync();

      ImageCartoon.Source = _cartoonImageBitmap;
    }

}

I just changed with SaveJpeg and it works now. Thanks for your help.

Thomas Salandre
  • 817
  • 3
  • 14
  • 27