none
WPF - UriSource eines Objektes RRS feed

  • Frage

  • Hallo,

    ich habe ein RenderTargetBitmap als Objekt hinterlegt. Nun möchte ich dazu ein Vorschaubild generieren (also mit kleinerer Auflösung), ohne dabei über eine temporäre Datei zu gehen. Wie kann ich ein Objekt als UriSource angeben? Das ganze sollte möglichst schnell sein, daher arbeite ich hier nur ungern mit temporären Dateien. Mein Code (mit ungültigen UriSource Parameter):

    RenderTargetBitmap cacheSaveImg = new RenderTargetBitmap();
    //Ein Bild anlegen
    //...
    
    //Vorschaubild generieren
    BitmapImage bmpImg = new BitmapImage();
    bmpImg.BeginInit();
    bmpImg.CacheOption = BitmapCacheOption.OnLoad;
    bmpImg.DecodePixelHeight = 240;
    bmpImg.UriSource = cacheSaveImg;
    bmpImg.EndInit();
    bmpImg.Freeze();

    Donnerstag, 22. Februar 2018 18:32

Antworten

  • Hi User,
    Du kannst über ein Byte-Array Dein Ansinnen ausführen, ohne auf Dateien zurückzugreifen. Hier mal eine kleine Demo:

    XAML:

    <Window x:Class="WpfApp1CS.Window35"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
            xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
            xmlns:local="clr-namespace:WpfApp1CS"
            mc:Ignorable="d"
            Title="Window35" Height="300" Width="300">
      <Window.Resources>
        <local:Window35VM x:Key="vm"/>
      </Window.Resources>
      <Grid DataContext="{StaticResource vm}">
        <Grid.ColumnDefinitions>
          <ColumnDefinition/>
          <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        <Border Grid.Column="0" BorderBrush="Green" BorderThickness="2" Margin="5">
          <Image Source="{Binding Bild1}"/>
        </Border>
        <Border Grid.Column="1" BorderBrush="DarkSalmon" BorderThickness="2" Margin="5">
          <Image Source="{Binding Bild2}"/>
        </Border>
      </Grid>
    </Window>
    

    ViewModel dazu:

    using System.Globalization;
    using System.Windows;
    using System.Windows.Media;
    using System.Windows.Media.Imaging;
    
    namespace WpfApp1CS
    {
      public class Window35VM
      {
        public RenderTargetBitmap Bild1 { get { return GetBitmap(); } }
    
        public RenderTargetBitmap Bild2
        {
          get
          {
            // neue Größe
            int newWidth = 100;
            int newHeight = 100;
            // Schritt 1: Pixel-Array erzeugen und füllen
            RenderTargetBitmap bmp1 = GetBitmap();
            int stride1 = newWidth * (bmp1.Format.BitsPerPixel + 7) / 8;
            byte[] data = new byte[stride1 * bmp1.PixelHeight];
            bmp1.CopyPixels(new Int32Rect(0, 0, newWidth, newHeight), data, stride1, 0);
            // Schritt 2: aus Pixel-Array neue ImageSource erzeugen
            PixelFormat pf = PixelFormats.Bgr32;
            int stride2 = newWidth * (pf.BitsPerPixel + 7) / 8;
            ImageSource bmps = BitmapSource.Create(newWidth, newHeight, 96, 96, pf, null, data, stride2);
            // Schritt 3: aus ImageSource neues RenderTargetBitmap erzeuegn und füllen
            RenderTargetBitmap bmp2 = new RenderTargetBitmap(100, 100, 96, 96, PixelFormats.Pbgra32);
            DrawingVisual dv = new DrawingVisual();
            DrawingContext dctx = dv.RenderOpen();
            dctx.DrawImage(bmps, new Rect(0, 0, 100, 100));
            dctx.Close();
            bmp2.Render(dv);
            return bmp2;
          }
        }
    
        RenderTargetBitmap bmp;
        private RenderTargetBitmap GetBitmap()
        {
          if (bmp == null)
          {
            FormattedText txt = new FormattedText("Demo",
                    new CultureInfo("de-de"),
                    FlowDirection.LeftToRight,
                    new Typeface(new FontFamily(), FontStyles.Normal, FontWeights.Normal, new FontStretch()),
                    20,
                    Brushes.Red);
            DrawingVisual dv = new DrawingVisual();
            DrawingContext dctx = dv.RenderOpen();
            dctx.DrawRectangle(Brushes.Yellow, new Pen(Brushes.Blue, 4), new Rect(2, 2, 196, 196));
            dctx.DrawText(txt, new Point(10, 10));
            dctx.Close();
            bmp = new RenderTargetBitmap(200, 200, 96, 96, PixelFormats.Pbgra32);
            bmp.Render(dv);
          }
          return bmp;
        }
      }
    }
    


    --
    Viele Grüsse
    Peter Fleischer (ehem. MVP)
    Meine Homepage mit Tipps und Tricks

    Freitag, 23. Februar 2018 08:21

Alle Antworten

  • Schau mal HIER, da wird ähnliches gemacht.

    Gruß, Stefan


    Freiberufler im Bereich Softwareentwicklung Von der PLC und Robotik zu VB.NET & C#, vorrangig WPF und UWP

    Donnerstag, 22. Februar 2018 18:37
  • Leider wird dort der Umweg über eine Datei gemacht. Also eine Datei wird zwei mal mit unterschiedlichen Auflösungen geladen. Meine Frage war, ob man nicht direkt das Bild aus dem RAM (in meinem Fall cacheSaveImg) nehmen kann, um eine Vorschau zu erstellen.
    Donnerstag, 22. Februar 2018 19:11
  • Hallo,

    Du kannst das mit einer Bitmap oder mit Graphics machen. Schau mal hier link. Ich bevorzuge meist die Bitmap da sie handlicher ist und es stehen alle Möglichkeiten offen


    Gruß Thomas
    Sage nie, ich kann es nicht - sage nur, ich kann es noch nicht!
    Dev Apps von mir: Icon für UWP,  UI Strings
    Andere Dev Apps: UWP Community Toolkit Sample App

    Freitag, 23. Februar 2018 00:18
  • Hi User,
    Du kannst über ein Byte-Array Dein Ansinnen ausführen, ohne auf Dateien zurückzugreifen. Hier mal eine kleine Demo:

    XAML:

    <Window x:Class="WpfApp1CS.Window35"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
            xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
            xmlns:local="clr-namespace:WpfApp1CS"
            mc:Ignorable="d"
            Title="Window35" Height="300" Width="300">
      <Window.Resources>
        <local:Window35VM x:Key="vm"/>
      </Window.Resources>
      <Grid DataContext="{StaticResource vm}">
        <Grid.ColumnDefinitions>
          <ColumnDefinition/>
          <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        <Border Grid.Column="0" BorderBrush="Green" BorderThickness="2" Margin="5">
          <Image Source="{Binding Bild1}"/>
        </Border>
        <Border Grid.Column="1" BorderBrush="DarkSalmon" BorderThickness="2" Margin="5">
          <Image Source="{Binding Bild2}"/>
        </Border>
      </Grid>
    </Window>
    

    ViewModel dazu:

    using System.Globalization;
    using System.Windows;
    using System.Windows.Media;
    using System.Windows.Media.Imaging;
    
    namespace WpfApp1CS
    {
      public class Window35VM
      {
        public RenderTargetBitmap Bild1 { get { return GetBitmap(); } }
    
        public RenderTargetBitmap Bild2
        {
          get
          {
            // neue Größe
            int newWidth = 100;
            int newHeight = 100;
            // Schritt 1: Pixel-Array erzeugen und füllen
            RenderTargetBitmap bmp1 = GetBitmap();
            int stride1 = newWidth * (bmp1.Format.BitsPerPixel + 7) / 8;
            byte[] data = new byte[stride1 * bmp1.PixelHeight];
            bmp1.CopyPixels(new Int32Rect(0, 0, newWidth, newHeight), data, stride1, 0);
            // Schritt 2: aus Pixel-Array neue ImageSource erzeugen
            PixelFormat pf = PixelFormats.Bgr32;
            int stride2 = newWidth * (pf.BitsPerPixel + 7) / 8;
            ImageSource bmps = BitmapSource.Create(newWidth, newHeight, 96, 96, pf, null, data, stride2);
            // Schritt 3: aus ImageSource neues RenderTargetBitmap erzeuegn und füllen
            RenderTargetBitmap bmp2 = new RenderTargetBitmap(100, 100, 96, 96, PixelFormats.Pbgra32);
            DrawingVisual dv = new DrawingVisual();
            DrawingContext dctx = dv.RenderOpen();
            dctx.DrawImage(bmps, new Rect(0, 0, 100, 100));
            dctx.Close();
            bmp2.Render(dv);
            return bmp2;
          }
        }
    
        RenderTargetBitmap bmp;
        private RenderTargetBitmap GetBitmap()
        {
          if (bmp == null)
          {
            FormattedText txt = new FormattedText("Demo",
                    new CultureInfo("de-de"),
                    FlowDirection.LeftToRight,
                    new Typeface(new FontFamily(), FontStyles.Normal, FontWeights.Normal, new FontStretch()),
                    20,
                    Brushes.Red);
            DrawingVisual dv = new DrawingVisual();
            DrawingContext dctx = dv.RenderOpen();
            dctx.DrawRectangle(Brushes.Yellow, new Pen(Brushes.Blue, 4), new Rect(2, 2, 196, 196));
            dctx.DrawText(txt, new Point(10, 10));
            dctx.Close();
            bmp = new RenderTargetBitmap(200, 200, 96, 96, PixelFormats.Pbgra32);
            bmp.Render(dv);
          }
          return bmp;
        }
      }
    }
    


    --
    Viele Grüsse
    Peter Fleischer (ehem. MVP)
    Meine Homepage mit Tipps und Tricks

    Freitag, 23. Februar 2018 08:21