locked
RenderTargetBitmap, whats going on? RRS feed

  • Question

  • Hi

     

    I try to make a copy of an element with some text elements inside, but when I use RenderTargetBitmap then my output gets very blurry. Please help, I've been trying everything but the right solution, for the last 3 days. 

     

    PLEASE HELP ME.

     

    I've made an little example to show my problem.

     

    XAML

     

    Code Snippet

    <Window

    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

    x:Class="CopyExample.Window1"

    x:Name="Window"

    Title="Window1"

    Width="640" Height="480" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d">

     

    <Grid x:Name="LayoutRoot">

     

    <Grid HorizontalAlignment="Left" x:Name="MyGrid" VerticalAlignment="Top" Width="198" Height="155" Background="#FFA9FFE5">

     

    <TextBlock HorizontalAlignment="Left" VerticalAlignment="Top" FontSize="18" Foreground="#FFFF0000" Text="TextBlock" TextWrapping="Wrap"/>

     

    <TextBlock HorizontalAlignment="Left" VerticalAlignment="Top" FontSize="18" Foreground="#FFFF0000" Text="TextBlock" TextWrapping="Wrap" Margin="0,23.94,0,0"/>

     

    <TextBlock HorizontalAlignment="Left" VerticalAlignment="Top" FontSize="18" Foreground="#FFFF0000" Text="TextBlock" TextWrapping="Wrap" Margin="0,47.88,0,0"/>

     

    <TextBlock HorizontalAlignment="Left" FontSize="18" Foreground="#FFFF0000" Text="TextBlock" TextWrapping="Wrap" Margin="0,71.82,0,59.24" d:LayoutOverrides="Height"/>

    </Grid>

     

    <Rectangle HorizontalAlignment="Left" VerticalAlignment="Top" Width="{Binding Path=ActualWidth, ElementName=MyGrid, Mode=Default}" Height="{Binding Path=ActualHeight, ElementName=MyGrid, Mode=Default}" Fill="#FFFF0000" Stroke="{x:Null}" x:Name="MyMirror" StrokeThickness="0" Visibility="Hidden"/>

     

    <Button HorizontalAlignment="Left" Margin="8,171,0,0" VerticalAlignment="Top" Width="94" Height="29" Content="Make Mirror" Click="Button_Click"/>

     

    </Grid>

    </Window>

     

     

    Code behind

    Code Snippet

    using System;

    using System.Collections.Generic;

    using System.Linq;

    using System.Text;

    using System.Windows;

    using System.Windows.Controls;

    using System.Windows.Data;

    using System.Windows.Documents;

    using System.Windows.Input;

    using System.Windows.Media;

    using System.Windows.Media.Imaging;

    using System.Windows.Shapes;

    namespace CopyExample

    {

    /// <summary>

    /// Interaction logic for Window1.xaml

    /// </summary>

    public partial class Window1 : Window

    {

    public Window1()

    {

    this.InitializeComponent();

    // Insert code required on object creation below this point.

    }

     

    public BitmapSource CopyElement(FrameworkElement source)

    {

    source.UpdateLayout();

    Size size = source.RenderSize;

    RenderTargetBitmap rtb = new RenderTargetBitmap(

    (int)size.Width, (int)size.Height, 96, 96, PixelFormats.Pbgra32);

    rtb.Render(source);

    return rtb;

    }

     

    private void Button_Click(object sender, RoutedEventArgs e)

    {

    if (MyMirror.Visibility == Visibility.Hidden)

    {

    MyMirror.Visibility = Visibility.Visible;

    MyMirror.Fill = new ImageBrush(CopyElement(MyGrid));

    }

    else

    MyMirror.Visibility = Visibility.Hidden;

    }

    }

    }

     

     

    Friday, April 18, 2008 6:56 PM

Answers

  • And one thing you need to know is that when the text is realized/rasterized into RenderTargetBitmap, the cleartype rendering algorithm will fallback to grayscale antialiasing which doesn't have the same text rendering quality of the original visuals.

    Hope this helps
    • Marked as answer by spandy Wednesday, June 18, 2008 5:45 AM
    Monday, April 21, 2008 8:20 AM

All replies

  • Try using explicit measurement of your source element before rendering to bitmap.

    Here's a sample on rendefing a Canvas to .png image

     

    Saving you canvas to image, XPS document or raw Xaml.

    http://dvuyka.spaces.live.com/blog/cns!305B02907E9BE19A!240.entry

    Friday, April 18, 2008 7:30 PM
  • Hi Denis Vuyka

     

    Thanks for your response, but it didn't do the trick, the output brush is still blurry and doesn't look like the source element..

     

    I've changed CopyElement to:

     

    Code Snippet

    public BitmapSource CopyElement(FrameworkElement source)

    {

    source.UpdateLayout();

     

    // Save current source transform

    Transform transform = source.LayoutTransform;

     

    // reset current transform (in case it is scaled or rotated)

    source.LayoutTransform = null;

     

    // Get the size of source

    Size size = new Size(source.Width, source.Height);

     

    // Measure and arrange the source

    // VERY IMPORTANT

    source.Measure(size);

    source.Arrange(new Rect(size));

     

    // Create a render bitmap and push the source to it

    RenderTargetBitmap renderBitmap = new RenderTargetBitmap((int)size.Width, (int)size.Height, 96d, 96d, PixelFormats.Pbgra32);

    renderBitmap.Render(source);

    source.LayoutTransform = transform;

    return renderBitmap;

    }

     

     

     

    Friday, April 18, 2008 7:48 PM
  • Anyone??? I'm pretty stocked here Sad

     

    When I try to make a rectangle with fill set as a visual brush pointing at MyGrid, it looks perfect. How can I get the same effect using RenderTargetBitmap?

     

    Can you get my sample to work, and you will be my new best friend ;-)

     

    Spandy

    Friday, April 18, 2008 11:16 PM
  • I think you are searching the problems in the wrong place. Guess this is layouting problem but not the rendering.

    Try making your Rectangle Visible and test the rendering

    <Rectangle

    HorizontalAlignment="Left"

    VerticalAlignment="Top"

    Width="{Binding Path=ActualWidth, ElementName=MyGrid, Mode=Default}"

    Height="{Binding Path=ActualHeight, ElementName=MyGrid, Mode=Default}"

    Fill="#FFFF0000"

    Stroke="{x:Null}"

    x:Name="MyMirror"

    StrokeThickness="0"

    Visibility="Visible"/>

     

    I've set the Visibility to "Visible" and rendering is not blurry.

    Also I've used either the last code (from the article) wrapped with your method

     

    MyMirror.Visibility = Visibility.Visible;

    MyMirror.Fill = new ImageBrush(CopyElement(MyGrid));

     

    and another lightweight one

     

    MyMirror.Visibility = Visibility.Visible;

    VisualBrush vb = new VisualBrush(MyGrid);

    vb.Viewbox = new Rect(new Size(MyGrid.ActualWidth, MyGrid.ActualHeight));

    vb.Viewport = new Rect(new Size(MyGrid.ActualWidth, MyGrid.ActualHeight));

    MyMirror.Fill = vb;

     

    and both rendering fine.

    Try elaborating on the layout as this is the root of your problem

    Saturday, April 19, 2008 8:28 AM
  • Hi Denis Vuyka

     

    I've done the above, but with no luck. I've made some small changes in the xaml, so you can see the blurry stuff a little better. I want the output to be exactly like the element, for that reason I've put the rectangle on top of the element, so I can see the difference. The textbox elements inside the MyGrid is jumping around and is very blurry on the MyMirror.

     

    Can you please try this Xaml then you know exactly what I mean.

     

    XAML

     

    Code Snippet

    <Window
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
     x:Class="CopyExample.Window1"
     x:Name="Window"
     Title="Window1"
     Width="640" Height="480" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d">

     <Grid x:Name="LayoutRoot">
      <Grid HorizontalAlignment="Left" x:Name="MyGrid" VerticalAlignment="Top" Width="198" Height="167" Background="#FFA9FFE5">
       <Border Margin="59.153,0,23.154,0" BorderThickness="2,2,2,2" BorderBrush="#FF000000" CornerRadius="5,5,5,5">
        <Border.Background>
         <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
          <GradientStop Color="#FF000000" Offset="0"/>
          <GradientStop Color="#FFFFFFFF" Offset="1"/>
         </LinearGradientBrush>
        </Border.Background>
        <Grid HorizontalAlignment="Center" VerticalAlignment="Stretch" Width="Auto">
         <TextBlock Margin="0,0,0,8" FontSize="18" Foreground="#FFFF0000" Text="TextBlock" TextWrapping="Wrap"/>
         <TextBlock FontSize="18" Foreground="#FFFF0000" Text="TextBlock" TextWrapping="Wrap" Margin="0,55.06,0,76"/>
         <TextBlock FontSize="18" Foreground="#FFFF0000" Text="TextBlock" TextWrapping="Wrap" Height="23.94" VerticalAlignment="Bottom" Margin="0,0,0,48"/>
         <TextBlock FontSize="18" Foreground="#FF000000" Text="TextBlock" TextWrapping="Wrap" Height="23.94" VerticalAlignment="Bottom" Margin="0,0,0,23"/>
        </Grid>
       </Border>
      </Grid>
    <Rectangle
      VerticalAlignment="Top"
      Width="{Binding Path=ActualWidth, ElementName=MyGrid, Mode=Default}"
      Height="{Binding Path=ActualHeight, ElementName=MyGrid, Mode=Default}"
      Fill="#FFFF0000"
      Stroke="{x:Null}"
      x:Name="MyMirror"
      StrokeThickness="0"
      Visibility="Visible" HorizontalAlignment="Left"/>
      <Button HorizontalAlignment="Left" Margin="8,171,0,0" VerticalAlignment="Top" Width="94" Height="29" Content="Make Mirror" Click="Button_Click"/>
     </Grid>
    </Window>

     

     

     

    Saturday, April 19, 2008 9:29 AM
  • Guess this is some kind of issue related to color rendering or clear types. Try setting the Black color for your TexBlocks and there won't be blurring. Guess this requires further elaboration on the rendering process related to text

    Saturday, April 19, 2008 1:11 PM
  • Try creating the RenderTargetBitmap with the Size of the Target instead of the Size of the Source (as you do in CopyElement), at least as an experiment.  You may be getting artifacts of stretching.
    Sunday, April 20, 2008 2:11 PM
  • Can you also compare the behavior on both Vista and XP pro? Something tells me it might be different

    Sunday, April 20, 2008 4:55 PM
  • And one thing you need to know is that when the text is realized/rasterized into RenderTargetBitmap, the cleartype rendering algorithm will fallback to grayscale antialiasing which doesn't have the same text rendering quality of the original visuals.

    Hope this helps
    • Marked as answer by spandy Wednesday, June 18, 2008 5:45 AM
    Monday, April 21, 2008 8:20 AM
  • Thanks John Gossman, I'll try this when I get home from work.

     

    Wednesday, April 23, 2008 12:46 PM
  • Denis Vuyka

     

    You are right, I tried it on a windows XP and it helped on the blurry stuff. It only seems to get blurry on my windows vista.

     

    Spandy

     

    Wednesday, April 23, 2008 12:50 PM
  • Thanks Marco Zhou

     

    Is there an other way to have the quality the same? I'm making a bookflipper, and I need to get a copy of the current render output, so I can use this as the flipping page.

     

    Spandy

    Wednesday, April 23, 2008 12:53 PM
  • Hi Marco / spandy,


    I know this is an old post, but did you ever find a way to render text to an image without the cleartype down scaling?

    I wondered if there was an alternative to RenderTargetBitmap


    all the best


    tommy

    Sunday, March 13, 2011 7:46 PM