How to Drawing Text with Outline onto Images?

断了今生、忘了曾经 提交于 2019-12-18 12:00:40

问题


I have been searching and looking for Drawing text with outline onto images?

Here my code

    private static void tulisnamafile(string imagepath, string textnya)
    {

        Image image = Image.FromStream(new MemoryStream(File.ReadAllBytes(imagepath)));
        Bitmap newImage = new Bitmap(640, 380);
        using (Graphics g = Graphics.FromImage(newImage))
        {
            // Draw base image
            g.DrawImageUnscaled(image, 0, 0);
            //Static is HERE
            SolidBrush brushing = new SolidBrush(Color.White);
            Font font = new Font(("Comic Sans MS"), 20.0f);
            int napoint = newImage.Height - 90;
            int napointa = image.Width - 200;
            FontFamily ff = new FontFamily("Times New Roman");
            int fontSize = 24;
            Font f = new Font(ff, fontSize, FontStyle.Regular);
            StringFormat sf = new StringFormat();
            Rectangle displayRectangle = new Rectangle(new Point(5, napoint), new Size(newImage.Width - 1, newImage.Height - 1));
            g.DrawEllipse(Pens.Magenta, new Rectangle(0, 0, 1, 1));
            GraphicsPath gp = new GraphicsPath();
            gp.AddString(textnya, ff, (int)FontStyle.Bold, fontSize + 4, new Point(0, 0), sf);
            g.FillPath(Brushes.White, gp);
            g.DrawPath(Pens.Black, gp);

            g.Flush(FlushIntention.Sync);
            g.Dispose();
        }
        image.Dispose();
        string fileName = "ab.jpg";
        string path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, fileName);
        MessageBox.Show(path);
        newImage.Save(path, System.Drawing.Imaging.ImageFormat.Jpeg);
        newImage.Dispose();
    }

and Its the trigger

    private void button3_Click(object sender, EventArgs e)
    {

        string imagename = "C:\\Documents and Settings\\admin\\My Documents\\Visual Studio 2008\\Projects\\template\\template\\bin\\Debug\\bg.jpg";
        tulisnamafile(imagename, "SlimPort® SP1002; Connect mobile devices to any big screen. High Speed micro USB");

    }

Check the Code result:

Such messing result, UNWRAPPED and with white color

This what I want, and with wrapping?

I found in CodeProject but not luck, its using C++. Based someone in neowin and tried this one too..

But still not luck.

UPDATE:

Here my working code, for who maybe need it... based from Abdias Software's code ( check the answers ), I make small changes ( there some error in those code).

        private static void tulisnamafile(string imagepath, string textnya)
    {

        float fontSize = 22;

        Image image = Image.FromStream(new MemoryStream(File.ReadAllBytes(imagepath)));
        //some test image for this demo
        Bitmap bmp = (Bitmap)Image.FromFile(imagepath);
        Graphics g = Graphics.FromImage(bmp);

        //this will center align our text at the bottom of the image
        StringFormat sf = new StringFormat();
        sf.Alignment = StringAlignment.Center;
        sf.LineAlignment = StringAlignment.Far;

        //define a font to use.
        Font f = new Font("Impact", fontSize, FontStyle.Bold, GraphicsUnit.Pixel);

        //pen for outline - set width parameter
        Pen p = new Pen(ColorTranslator.FromHtml("#77090C"), 8);
        p.LineJoin = LineJoin.Round; //prevent "spikes" at the path

        //this makes the gradient repeat for each text line
        Rectangle fr = new Rectangle(0, bmp.Height - f.Height, bmp.Width, f.Height);
        LinearGradientBrush b = new LinearGradientBrush(fr,
                                                        ColorTranslator.FromHtml("#FF6493"),
                                                        ColorTranslator.FromHtml("#D00F14"),
                                                        90);

        //this will be the rectangle used to draw and auto-wrap the text.
        //basically = image size
        Rectangle r = new Rectangle(0, 0, bmp.Width, bmp.Height);

        GraphicsPath gp = new GraphicsPath();

        //look mom! no pre-wrapping!
        gp.AddString(textnya, f.FontFamily, (int)FontStyle.Bold, fontSize, r, sf);

        //these affect lines such as those in paths. Textrenderhint doesn't affect
        //text in a path as it is converted to ..well, a path.    
        g.SmoothingMode = SmoothingMode.AntiAlias;
        g.PixelOffsetMode = PixelOffsetMode.HighQuality;

        //TODO: shadow -> g.translate, fillpath once, remove translate
        g.DrawPath(p, gp);
        g.FillPath(b, gp);

        //cleanup
        gp.Dispose();
        b.Dispose();
        b.Dispose();
        f.Dispose();
        sf.Dispose();
        g.Dispose();
        string fileName = "ab.jpg";
        string path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, fileName);
        bmp.Save(path, System.Drawing.Imaging.ImageFormat.Jpeg);
        bmp.Dispose();
    }

回答1:


Just to sum up:

Define a GraphicPath and then use DrawPath to draw outlined version of text, FillPath to draw a filled version.

For the second image with the woman, a second (filled) version is drawn first at a small offset.

For the gradient use LinearGradientBrush for brush. Thickness of the outline is defined by the Pen's thickness.

For wrapping define a StringFormat and use a Rectangle to define the region you want the text to be in.

To center the text you can define the rectangle to have the same width as the image, then set strformat.Alignment to Center.

UPDATE: To replicate the text in the second image you can use this code:

float fontSize = 52;

//some test image for this demo
Bitmap bmp = (Bitmap)Image.FromFile(s"test.jpg");
Graphics g = Graphics.FromImage(bmp);

//this will center align our text at the bottom of the image
StringFormat sf = new StringFormat();
sf.Alignment = StringAlignment.Center;
sf.LineAlignment = StringAlignment.Far;

//define a font to use.
Font f = new Font("Impact", fontSize, FontStyle.Bold, GraphicsUnit.Pixel);

//pen for outline - set width parameter
Pen p = new Pen(ColorTranslator.FromHtml("#77090C"), 8);
p.LineJoin = LineJoin.Round; //prevent "spikes" at the path

//this makes the gradient repeat for each text line
Rectangle fr = new Rectangle(0, bmp.Height - f.Height, bmp.Width, f.Height);
LinearGradientBrush b = new LinearGradientBrush(fr,  
                                                ColorTranslator.FromHtml("#FF6493"),
                                                ColorTranslator.FromHtml("#D00F14"),
                                                90);

//this will be the rectangle used to draw and auto-wrap the text.
//basically = image size
Rectangle r = new Rectangle(0, 0, bmp.Width, bmp.Height);

GraphicsPath gp = new GraphicsPath();

//look mom! no pre-wrapping!
gp.AddString("Demo for Stack Overflow", 
             f.FontFamily, (int)f.Style, fontSize, r, sf);

//these affect lines such as those in paths. Textrenderhint doesn't affect
//text in a path as it is converted to ..well, a path.    
g.SmoothingMode = SmoothingMode.AntiAlias;
g.PixelOffsetMode = PixelOffsetMode.HighQuality;

//TODO: shadow -> g.translate, fillpath once, remove translate
g.DrawPath(p, gp);
g.FillPath(b, gp);

//cleanup
gp.Dispose();
b.Dispose();
b.Dispose();
f.Dispose();
sf.Dispose();
g.Dispose();

bmp.Save(s"test_result.jpg", System.Drawing.Imaging.ImageFormat.Jpeg);
bmp.Dispose();

This will produce this result:

To produce the extra "shadow" just translate the gfirst, draw filled, then remove the translation.

The FromHtml is used here as I picked the colors from your image and was to lazy to convert. Just use Color.FromARGB() or a fixed color - as you want.

VB version:

    Dim fontSize As Single = 52

    Dim bmp As Bitmap = Bitmap.FromFile("c:\test.jpg")
    Dim g As Graphics = Graphics.FromImage(bmp)

    Dim sf As New StringFormat(StringFormatFlags.NoClip)
    sf.Alignment = StringAlignment.Center
    sf.LineAlignment = StringAlignment.Far

    Dim f As New Font("Impact", fontSize, FontStyle.Bold, GraphicsUnit.Pixel)

    Dim p As New Pen(ColorTranslator.FromHtml("#77090C"), 4)
    p.LineJoin = LineJoin.Round

    'rectangle for font to repeat gradient for each line
    Dim fr As New Rectangle(0, bmp.Height - f.Height, bmp.Width, f.Height)
    Dim b As New LinearGradientBrush(fr,
                                     ColorTranslator.FromHtml("#FF6493"),
                                     ColorTranslator.FromHtml("#D00F14"),
                                     90)

    Dim r As New Rectangle(0, 0, bmp.Width, bmp.Height)
    Dim gp As New GraphicsPath

    gp.AddString("Demo for Stack Overflow",
                 f.FontFamily,
                 f.Style,
                 fontSize,
                 r,
                 sf)

    g.SmoothingMode = SmoothingMode.AntiAlias
    g.PixelOffsetMode = PixelOffsetMode.HighQuality

    g.DrawPath(p, gp)
    g.FillPath(b, gp)

    gp.Dispose() 'path
    b.Dispose() 'b
    b.Dispose()  'p
    f.Dispose()  'font
    sf.Dispose()  'stringformat
    g.Dispose()  'g

    bmp.Save("c:\test_result.jpg", Imaging.ImageFormat.Jpeg)
    bmp.Dispose()



回答2:


A simple way to get "better" results could be to draw the text twice. Draw the shadow first, for example some pixels to the right and to the bottom, if you want the classic drop-shadow look, in gray color. You may also want to consider using a different font, any font without serifs will look better i would guess. For the gradient effect see the msdn page or google how on how to use it. Also, play around with the SmoothingMode and TextRenderingHint of the graphics object, HighQuality and Antialias should produce better looking results.



来源:https://stackoverflow.com/questions/14077523/how-to-drawing-text-with-outline-onto-images

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!