Dans le cadre d’un projet, j’ai eu besoin de générer une image contenant d’autres images composées ainsi que du texte. Ceci devait être fait dans un thread séparé pour des raisons de performances.
Pour cela, il existe une technologie bien sympatique en WPF, le RenderTargetBitmap. Ce dernier permet en effet de dessiner des Visual directement dans son contenu. Pour ce faire on s’appuie sur la classe DrawingVisual qui est un peu l’équivalent de la classe Graphics en Windows Forms/GDI+.
Cette dernière permet par exemple de dessiner des images (et donc de les redimensionner) ainsi que du texte (notamment).
Cela donne donc ceci:
FormattedText text = new FormattedText("Message à caractère informatif",
new CultureInfo("en-us"), FlowDirection.LeftToRight,
new Typeface(new FontFamily("Arial"), FontStyles.Normal, FontWeights.Bold, new FontStretch())
, 18, Brushes.Black);
DrawingVisual drawingVisual = new DrawingVisual();
DrawingContext drawingContext = drawingVisual.RenderOpen();
drawingContext.DrawImage(image, new Rect(0, 0, renderTarget.PixelWidth, renderTarget.PixelHeight));
drawingContext.DrawText(text, new Point(renderTarget.PixelWidth - text.Width - 45, 350));
text.SetForegroundBrush(Brushes.White);
drawingContext.DrawText(text, new Point(renderTarget.PixelWidth - text.Width - 45 - 1, 349));
drawingContext.Close();
renderTarget.Render(drawingVisual);
Par la suite, ce RenderTargetBitmap peut servir de source à un contrôle Image ou peut être sauvegarder sur le disque via la classe BmpBitmapEncoder:
string picturePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments)
, "urza.bmp");
FileStream stream = new FileStream(picturePath, FileMode.Create);
BmpBitmapEncoder encoder = new BmpBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(renderTarget));
encoder.Save(stream);
Et le tour est joué!
.Net, WPF