3

Je tente de mettre un filigrane sur une photo prise par mon application. Le moyen le plus simple que je pourrais penser est d'utiliser FrameworkElement pour construire les couches et ensuite utiliser RenderTargetBitmap pour créer l'image marquée par l'eau.Windows Store App - RenderTargetBitmap créant un bitmap de taille incorrecte

Voici un exemple de mon XAML.

<ScrollViewer x:Name="Zoom" Grid.Column="1" HorizontalScrollMode="Enabled" VerticalScrollMode="Enabled" VerticalScrollBarVisibility="Hidden" HorizontalScrollBarVisibility="Hidden" ZoomMode="Enabled"> 
     <Border x:Name="BgBorder"> 
      <Grid x:Name="ImageGird" SizeChanged="ImageGird_SizeChanged"> 
       <Grid x:Name="CaptureGird"> 
        <Image x:Name="CapturedImage" Stretch="None" Source="ms-appx:///Assets/Photo.jpg" /> 
        <StackPanel x:Name="Watermark" VerticalAlignment="Top" HorizontalAlignment="Left" Background="#6FFFFFFF" Margin="10"> 
         <TextBlock Text="Name" Foreground="Black" Margin="10,2.5,10,2.5" /> 
         <TextBlock Text="12345" Foreground="Black" Margin="10,2.5,10,2.5"/> 
         <TextBlock Text="54321" Foreground="Black" Margin="10,2.5,10,2.5" /> 
        </StackPanel> 
       </Grid> 
      </Grid> 
     </Border> 
    </ScrollViewer> 

En raison de la résolution des images dont ils ont besoin, il est enveloppé dans un ScrollViewer il peut être zoomée, cependant lorsque je tente de créer un bitmap de cette image en utilisant le code ci-dessous, le bitmap rendu est plus petit alors le FrameworkElement

private async void Button_Click(object sender, RoutedEventArgs e) 
{ 
    try 
    { 
     var displayI = DisplayInformation.GetForCurrentView(); 
     var renderTargetBitmap = new RenderTargetBitmap(); 
     await renderTargetBitmap.RenderAsync(ImageGird, (int)ImageGird.ActualWidth, (int)ImageGird.ActualHeight); 
     IBuffer pixels = await renderTargetBitmap.GetPixelsAsync(); 
     CapturedImage2.Source = renderTargetBitmap; 

     Debug.WriteLine("Button_Click: ImageGrid: " + ImageGird.ActualWidth + "x" + ImageGird.ActualHeight + " RenderTargetBitmap: " + renderTargetBitmap.PixelWidth + "x" + renderTargetBitmap.PixelHeight); 
    } 
    catch (Exception) 
    { 
    } 
} 

la sortie de débogage est

Button_Click: ImageGrid: 5344x3008 RenderTargetBitmap: 4096x2306 

quelqu'un peut-il me dire pourquoi le bitmap rendu est beaucoup plus petite que la ele réelle Je le crée depuis?

Existe-t-il également un meilleur moyen de filigrane d'une image?

Répondre

1

Merci à @ A.J.Bauer me montrant à Win2D j'ai réussi à résoudre le problème assez élégamment.

/// <summary> 
    /// Create a watermarked image from an image stream 
    /// </summary> 
    /// <param name="sender">Jpeg image stream.</param> 
    private async Task<ImageSource> CreateWaterMarkedImage(IRandomAccessStream stream) 
    { 
     // Ensure our stream is at the beginning. 
     stream.Seek(0); 
     // Create our Win2D in memory renderer. 
     CanvasDevice device = CanvasDevice.GetSharedDevice(); 
     CanvasRenderTarget offscreen = new CanvasRenderTarget(device, (float)ImageGird.ActualWidth, (float)ImageGird.ActualHeight, 96); 
     // Create our Win2D bitmap 
     CanvasBitmap bmp = await CanvasBitmap.LoadAsync(offscreen, stream, 96); 
     // Create a text formatter for our watermark 
     var format = new CanvasTextFormat() 
     { 
      FontSize = 40, 
      HorizontalAlignment = CanvasHorizontalAlignment.Left, 
      VerticalAlignment = CanvasVerticalAlignment.Top, 
      WordWrapping = CanvasWordWrapping.Wrap, 
      FontFamily = "Arial", 
      FontWeight = FontWeights.SemiBold 
     }; 
     // Get a Win2D drawing session instance 
     using (CanvasDrawingSession ds = offscreen.CreateDrawingSession()) 
     { 
      // Layer our resulting Watermarked image. 
      ds.DrawImage(bmp); 
      // Create the Win2D text layout so we can get the bounds. 
      var tl = new CanvasTextLayout(ds, "Name\r\n12345\r\n54321", format, 1000, 1000); 
      // Create a background for the text 
      ds.FillRectangle(10, 10, (float)tl.DrawBounds.Width + 20f, (float)tl.DrawBounds.Height + 20f, new Color() { A = 0x6F, R = 0xFF, G = 0xFF, B = 0xFF }); 
      // Add the text layout. 
      ds.DrawTextLayout(tl, 10, 10, Colors.Black); 
      // Clear up the memory. 
      tl.Dispose(); 
     } 

     // Create our bitmap so we can return an ImageSource 
     BitmapImage im = new BitmapImage(); 
     using (InMemoryRandomAccessStream oStream = new InMemoryRandomAccessStream()) 
     { 
      // Save the Win2D canvas renderer a stream. 
      await offscreen.SaveAsync(oStream, CanvasBitmapFileFormat.Jpeg, 1.0f); 
      stream.Seek(0); 
      // Stream our Win2D pixels into the Bitmap 
      await im.SetSourceAsync(oStream); 
      Debug.WriteLine("CreateWaterMarkedImage: ImageGrid: " + ImageGird.ActualWidth + "x" + ImageGird.ActualHeight + " Bitmap: " + im.PixelWidth + "x" + im.PixelHeight); 
     } 
     // Tidy Up. 
     format.Dispose(); 
     bmp.Dispose(); 
     offscreen.Dispose(); 
     device.Dispose(); 
     return im; 
    } 

Le débogage résultant me donne.

CreateWaterMarkedImage: ImageGrid: 5344x3008 Bitmap: 5344x3008 

Et si définir la source d'un ImageUIElement l'image tatouée est affichée.

CapturedImage2.Source = await CreateWaterMarkedImage(photoStream); 

Cet exemple est très adapté à mes besoins, mais tout le monde devrait facilement être en mesure de l'adapter si vous utilisez les commandes Win2D XAML.

1

Les valeurs ActualWidth et ActualHeight sont des valeurs calculées. Donc, surtout pour une grille, il est logique que ces valeurs puissent changer au fil du temps. Je suppose que lorsque vous définissez la source d'image que la largeur et la hauteur réelles sont recalculées.

Je pense que vous devriez être en mesure de faire du panneau de pile un enfant de l'image et de le positionner par rapport à l'image parente, cela le ferait fonctionner pour des tailles d'image variables. Vous pouvez également essayer de placer des contraintes sur la grille et les utiliser pour déterminer la taille de votre bitmap au lieu d'utiliser la largeur/hauteur réelle.

1

Havel a Regardez Win2D et utilisez le dessin hors écran.

+0

Cela semble intéressant. Je vais vérifier, je suis surpris de ne pas être tombé sur cette bibliothèque. – Ne0

+0

Btw: La galerie d'exemples est également disponible dans Windows 10 Store. Rechercher: Win2D –