Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/269.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在现有图像文件上写入文本?_C#_.net_Wpf_Visual Studio - Fatal编程技术网

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

C# 在现有图像文件上写入文本?,c#,.net,wpf,visual-studio,C#,.net,Wpf,Visual Studio,所以我在WinForms.NET3.5中做这个。。。我现在正在使用WPF.NET4.0。。。我不知道该怎么做 这就是我在Windows.NET3.5中所做的 using (Bitmap eventImg = new Bitmap("input.png")) { Graphics eventGfx = Graphics.FromImage(eventImg); buildText(eventGfx, this.event1.Text); eventImg.Save("o

所以我在WinForms.NET3.5中做这个。。。我现在正在使用WPF.NET4.0。。。我不知道该怎么做

这就是我在Windows.NET3.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();
}
上面的代码在“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);
    }
}
然而,由于System.Drawing在WPF.NET4.0中不存在,我不能再使用这些函数了。我将如何做我在WPF.NET4.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);
}

在WPF中,不允许使用图形,因为WPF提供了新的tec。这样做。 图形引用旧的Windows API,但WPF使用DirectX。例如,WPF不再适用于像素等


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

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);
        }
    }
}
您可以将此方法用于对象和位置:

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));
编辑:如果要绘制相对于某个矩形水平和垂直对齐的文本,可以将
位置
参数替换为该矩形和两个对齐参数,并按如下方式计算文本位置:

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);
        }
    }
}
WriteTextToImage(@"C:\Users\Public\Pictures\Sample Pictures\Desert.jpg", "Desert.png", text,
    new Rect(80, 50, 430, 200),
    HorizontalAlignment.Center, VerticalAlignment.Center);
现在您可以使用如下方法:

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);
        }
    }
}
WriteTextToImage(@"C:\Users\Public\Pictures\Sample Pictures\Desert.jpg", "Desert.png", text,
    new Rect(80, 50, 430, 200),
    HorizontalAlignment.Center, VerticalAlignment.Center);

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

<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>


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

,您可以将位图加载到一个图像元素中,该图像元素上只包含一个文本元素,然后将父容器渲染为可写位图并保存该位图。HiTech,你能详细解释一下怎么做吗?这是我第一次使用WPF。好吧,这正是我想要的。。。然而,有一个根本问题。DrawText将文本放置在具有新点(x,y)的特定x,y坐标处。问题是,有时我的文本集中在一个矩形区域内。有没有办法将文本绘制到一个矩形区域,然后用垂直对齐和水平对齐对齐文本?@JasonAxelrod计算对齐文本的位置非常简单,因为您知道图像的大小和文本的大小。看我编辑的答案。我不知道,数学对我来说没有意义。。。好的,假设图像宽度是
1280
;我想将文本对齐在一个矩形区域中,从
80
(存储在一个名为
left
的变量中)的像素开始。矩形区域的宽度为
430
(存储在名为
width
的变量中)像素。我该如何计算使文本中心在矩形区域内对齐。。。对吗?我绞尽脑汁想弄清楚数学。。。但这对我来说毫无意义。你不认为是时候自己做一些研究了吗?有大量关于WPF的文档。请参阅关于
em
size。