wpf 在现有图像文件上写入文本?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11903218/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-13 04:56:35  来源:igfitidea点击:

Write text on top of existing image file?

c#.netwpfvisual-studio

提问by Jason Axelrod

So I was doing this in WinForms .NET 3.5... I am now using WPF .NET 4.0... and I cant figure out how to do it.

所以我在 WinForms .NET 3.5 中这样做......我现在正在使用 WPF .NET 4.0......我不知道如何去做。

This is what I was doing in Windows .NET 3.5

这就是我在 Windows .NET 3.5 中所做的

using (Bitmap eventImg = new Bitmap("input.png"))
{
    Graphics eventGfx = Graphics.FromImage(eventImg);

    buildText(eventGfx, this.event1.Text);

    eventImg.Save("output.png", ImageFormat.Png);
    eventGfx.Dispose();
}

The above code took the existing image at "input.png", created a new image from it, wrote text from it and then saved the new image at "output.png". Text was written using the following function:

上面的代码采用“input.png”中的现有图像,从中创建一个新图像,从中写入文本,然后将新图像保存在“output.png”中。文本是使用以下函数编写的:

private void buildText(Graphics graphic, string text)
{
    if (text.Length == 0) { return; }

    FontStyle weight = FontStyle.Regular;

    switch (this.font_style)
    {
        case "regular":     weight = FontStyle.Regular;     break;
        case "bold":        weight = FontStyle.Bold;        break;
        case "italic":      weight = FontStyle.Italic;      break;
        case "underline":   weight = FontStyle.Underline;   break;
        case "strikeout":   weight = FontStyle.Strikeout;   break;
    }

    using (Font font = new Font(this.font_family, this.font_size, weight, GraphicsUnit.Pixel))
    {
        Rectangle rect = new Rectangle(this.left, this.top, this.width, this.height);
        Brush brush = new SolidBrush(Color.FromArgb(this.font_color));

        StringFormat format = new StringFormat();

        switch (this.align_x)
        {
            case "left":    format.Alignment = StringAlignment.Near;     break;
            case "right":   format.Alignment = StringAlignment.Far;      break;
            default:        format.Alignment = StringAlignment.Center;   break;
        }

        switch (this.align_y)
        {
            case "top":     format.LineAlignment = StringAlignment.Near;    break;
            case "bottom":  format.LineAlignment = StringAlignment.Far;     break;
            default:        format.LineAlignment = StringAlignment.Center;  break;
        }

        graphic.TextRenderingHint = TextRenderingHint.AntiAlias;
        graphic.DrawString(text, font, brush, rect, format);
    }
}

However, since System.Drawing does not exist in WPF .NET 4.0, I can't use these functions anymore. How would I do what I am trying to do in WPF .NET 4.0? I've gotten as far as the code below in order to do the first step of making an image based on the old image:

但是,由于 WPF .NET 4.0 中不存在 System.Drawing,因此我无法再使用这些功能。我将如何在 WPF .NET 4.0 中做我想做的事?为了做基于旧图像制作图像的第一步,我已经得到了下面的代码:

using (var fileStream = new FileStream(@"z:\ouput.png", FileMode.Create))
{
    BitmapEncoder encoder = new PngBitmapEncoder();
    encoder.Frames.Add(BitmapFrame.Create(new Uri(@"z:\input.png")));
    encoder.Save(fileStream);
}

回答by Clemens

Having read answers and comments here I thought you might appreciate a more comprehensive solution. Here is a little method that does the job:

在这里阅读了答案和评论后,我认为您可能会喜欢更全面的解决方案。这是一个完成工作的小方法:

public static void WriteTextToImage(string inputFile, string outputFile, FormattedText text, Point position)
{
    BitmapImage bitmap = new BitmapImage(new Uri(inputFile)); // inputFile must be absolute path
    DrawingVisual visual = new DrawingVisual();

    using (DrawingContext dc = visual.RenderOpen())
    {
        dc.DrawImage(bitmap, new Rect(0, 0, bitmap.PixelWidth, bitmap.PixelHeight));
        dc.DrawText(text, position);
    }

    RenderTargetBitmap target = new RenderTargetBitmap(bitmap.PixelWidth, bitmap.PixelHeight,
                                                       bitmap.DpiX, bitmap.DpiY, PixelFormats.Default);
    target.Render(visual);

    BitmapEncoder encoder = null;

    switch (Path.GetExtension(outputFile))
    {
        case ".png":
            encoder = new PngBitmapEncoder();
            break;
        // more encoders here
    }

    if (encoder != null)
    {
        encoder.Frames.Add(BitmapFrame.Create(target));
        using (FileStream outputStream = new FileStream(outputFile, FileMode.Create))
        {
            encoder.Save(outputStream);
        }
    }
}

You would use this method with a FormattedTextobject and a position:

您可以将此方法与FormattedText对象和位置一起使用:

FormattedText text = new FormattedText(
    "Hello",
    CultureInfo.InvariantCulture,
    FlowDirection.LeftToRight,
    new Typeface("Segeo UI"),
    20,
    Brushes.Red);

WriteTextToImage(
    @"C:\Users\Public\Pictures\Sample Pictures\Desert.jpg",
    "Desert.png",
    text,
    new Point(10, 10));

EDIT: If you want to draw the text horizontally and vertically aligned relative to a certain rectangle, you might replace the positionparameter by that rectangle and two alignment parameters and calculate the text position like this:

编辑:如果要绘制相对于某个矩形水平和垂直对齐的文本,您可以将该position参数替换为该矩形和两个对齐参数,并像这样计算文本位置:

public static void WriteTextToImage(string inputFile, string outputFile, FormattedText text,
    Rect textRect, HorizontalAlignment hAlign, VerticalAlignment vAlign)
{
    BitmapImage bitmap = new BitmapImage(new Uri(inputFile));
    DrawingVisual visual = new DrawingVisual();
    Point position = textRect.Location;

    switch (hAlign)
    {
        case HorizontalAlignment.Center:
            position.X += (textRect.Width - text.Width) / 2;
            break;
        case HorizontalAlignment.Right:
            position.X += textRect.Width - text.Width;
            break;
    }

    switch (vAlign)
    {
        case VerticalAlignment.Center:
            position.Y += (textRect.Height - text.Height) / 2;
            break;
        case VerticalAlignment.Bottom:
            position.Y += textRect.Height - text.Height;
            break;
    }

    using (DrawingContext dc = visual.RenderOpen())
    {
        dc.DrawImage(bitmap, new Rect(0, 0, bitmap.PixelWidth, bitmap.PixelHeight));
        dc.DrawText(text, position);
    }

    RenderTargetBitmap target = new RenderTargetBitmap(bitmap.PixelWidth, bitmap.PixelHeight,
                                                       bitmap.DpiX, bitmap.DpiY, PixelFormats.Default);
    target.Render(visual);

    BitmapEncoder encoder = null;

    switch (Path.GetExtension(outputFile))
    {
        case ".png":
            encoder = new PngBitmapEncoder();
            break;
        case ".jpg":
            encoder = new JpegBitmapEncoder();
            break;
    }

    if (encoder != null)
    {
        encoder.Frames.Add(BitmapFrame.Create(target));

        using (FileStream outputStream = new FileStream(outputFile, FileMode.Create))
        {
            encoder.Save(outputStream);
        }
    }
}

Now you might use the method like this:

现在你可以使用这样的方法:

WriteTextToImage(@"C:\Users\Public\Pictures\Sample Pictures\Desert.jpg", "Desert.png", text,
    new Rect(80, 50, 430, 200),
    HorizontalAlignment.Center, VerticalAlignment.Center);

回答by makc

you can use grid or any other panel which suits your needs in the following way

您可以通过以下方式使用网格或任何其他适合您需求的面板

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto" />
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="Auto" /> 
    </Grid.ColumnDefinitions>

    <Image x:name="My image" .. bind it to the bintmap 
           Grid.row="0"
           Grid.colomn="0"/>
    <TextBlock x:name="MyText"  
               Text="....."
                Grid.row="0"
                Grid.colomn="0"/>
</Grid>

the text and the image are drawn in the same space in the grid and you can manipulate the alignment anyway you like

文本和图像绘制在网格中的相同空间中,您可以随意操纵对齐方式

回答by Florian

In WPF you are not allowed to use Graphics because wpf offers new tec. to do that. Graphics referes to old Windows API's but WPF uses DirectX. As example WPF does not work anymore with pixels and so on.

在 WPF 中,您不允许使用 Graphics,因为 wpf 提供了新的技术。要做到这一点。图形是指旧的 Windows API,但 WPF 使用 DirectX。例如,WPF 不再适用于像素等。

http://msdn.microsoft.com/de-de/library/system.windows.media.drawingcontext.aspx

http://msdn.microsoft.com/de-de/library/system.windows.media.drawingcontext.aspx