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.

有帮助吗?

解决方案 2

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.

其他提示

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!

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top