在位图上绘制对角线文本

Posted

技术标签:

【中文标题】在位图上绘制对角线文本【英文标题】:Drawing Diagonal Text all over Bitmap 【发布时间】:2022-01-15 17:09:18 【问题描述】:

我正在使用以下代码在整个图像上绘制倾斜的文本。这可以工作,但不是预期的。

Bitmap bmp = new Bitmap(pictureBox1.Image);
Graphics g = Graphics.FromImage(bmp);
String text = "TextTile";

Font font = new Font(DefaultFont.Name, 20);
SizeF size = g.MeasureString(text, font);
int textwidth = size.ToSize().Width;
int textheight = size.ToSize().Height;

int y_offset = (int)(textwidth * Math.Sin(45 * Math.PI / 180.0));

//the sin of the angle may return zero or negative value, 
//it won't work with this formula
if (y_offset >= 0)

    for (int x = 0; x < bmp.Width; x += textwidth)
    
        for (int y = 0; y < bmp.Height; y += y_offset)
        
            //move to this position
            g.TranslateTransform(x, y);

            //draw text rotated around its center
            g.TranslateTransform(textwidth, textheight);
            g.RotateTransform(-45);
            g.TranslateTransform(-textwidth, -textheight);
            g.DrawString(text, font, Brushes.Yellow, 0, 0);

            //reset
            g.ResetTransform();
        
    


pictureBox1.Image = bmp;

这是代码的结果

我正在寻找类似于下图的内容,您可以看到同一行中有多行文本。另外,您将如何确定文本的字体大小,以便正确地为图像添加水印.

【问题讨论】:

【参考方案1】:

我使用Jen's explanation 找到旋转文本的边界框。

我从位图的左上角开始绘制一条向上和向右的重复文本的对角线。每次线离开右侧或顶部边缘时,我都会通过添加线总高度的两倍来开始一条新的对角线。当我绘制文本的每条对角线时,我会跟踪其中一个起始坐标是否在位图的范围内。当我找到一条没有穿过位图的整条线时,我就知道我们已经完成了。

*哦,我看到了你的 Leo DiCaprio 和 Chris Hemsworth。

当我尝试将文本的方向从左上角更改为底部时 右使用 45 而不是 -45 角度,我看到左侧有一个间隙 图片。

修改代码以处理两个方向。

注意对Watermark() 的两个不同调用,带有参数:

private void button1_Click(object sender, EventArgs e)

    Watermark(pictureBox1, WatermarkDirection.BottomLeftToTopRight, "Do not copy!");
    Watermark(pictureBox2, WatermarkDirection.TopLeftToBottomRight, "Proof");


enum WatermarkDirection

    BottomLeftToTopRight,
    TopLeftToBottomRight
    


private void Watermark(PictureBox pb, WatermarkDirection direction, String text)

    Bitmap bmp = new Bitmap(pb.Image);
    Rectangle rcBmp = new Rectangle(new Point(0, 0), bmp.Size);
    Graphics g = Graphics.FromImage(bmp);
    Font font = new Font(DefaultFont.Name, 20);
    SizeF size = g.MeasureString(text, font);
    int textwidth = (int)size.Width;
    int textheight = (int)size.Height;

    int angle = (direction == WatermarkDirection.BottomLeftToTopRight) ? -45 : 45;
    int y_main = Math.Abs((int)(textwidth * Math.Sin(angle * Math.PI / 180.0)));
    int x_main = Math.Abs((int)(textwidth * Math.Cos(angle * Math.PI / 180.0)));
    int y_add = Math.Abs((int)(textheight * Math.Cos(angle * Math.PI / 180.0)));
    int x_add = Math.Abs((int)(textheight * Math.Sin(angle * Math.PI / 180.0)));
    int totalX = x_main + x_add;
    int totalY = y_main + y_add;

    // keep going down until we find a line that doesn't cross our bmp
    Rectangle rcText;
    bool intersected = true;
    int multiplier = (direction == WatermarkDirection.BottomLeftToTopRight) ? 1 : -1;
    int offset = (direction == WatermarkDirection.BottomLeftToTopRight) ? -totalY : 0;            
    for (int startY = totalY; intersected; startY += (2 * totalY))
    
        intersected = false;
        int x = (direction == WatermarkDirection.BottomLeftToTopRight) ? 0 : (bmp.Width - totalX);
        int y = startY;
           
        rcText = new Rectangle(new Point(x, y + offset), new Size(totalX, totalY));
        if (rcBmp.IntersectsWith(rcText))  intersected = true; 
        while (((direction == WatermarkDirection.BottomLeftToTopRight) && (x <= bmp.Width || y >= 0)) ||
                ((direction == WatermarkDirection.TopLeftToBottomRight) && (x >=0 || y >= 0)))
                            
            g.TranslateTransform(x, y);
            g.RotateTransform(angle);
            g.DrawString(text, font, Brushes.Yellow, 0, 0);
            g.ResetTransform();
            
            x += (totalX * multiplier);
            y -= totalY;
            rcText = new Rectangle(new Point(x, y + offset), new Size(totalX, totalY));
            if (rcBmp.IntersectsWith(rcText))  intersected = true; 
        
    
    pb.Image = bmp;
    g.Dispose();
    font.Dispose();

样本输出:

【讨论】:

非常感谢您的努力。这很好:) 我有另一个问题。当我尝试将文本的方向更改为 - from top left to bottom right 使用45 而不是 -45 角度,我在图像的左侧看到了一个间隙。请参阅imgur.com/a/svxodFz 我将从我的工作计算机发布更新。 谢谢 .... .... 查看修改后的帖子和代码。 非常感谢...

以上是关于在位图上绘制对角线文本的主要内容,如果未能解决你的问题,请参考以下文章

如何在位图上绘制粗体文本?

Android 在位图上绘制文本

在位图上使用 DrawText() 时文本旋转?

在 WPF 中相对于其容器绘制对角文本/文本块/标签/控件

如何使用 EaselJS 在位图上绘制/绘制线条?

在位图上绘制椭圆并返回带有椭圆的位图