2

I'd like to have transparent watermark background image in my html document and print it. To do so, I created the following background image using svc data uri:

body {
    background-image: url("data:image/svg+xml;charset=UTF-8,%3Csvg%20xmlns%20%3D%20%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20version%20%3D%20%271.1%27%20height%20%3D%20%27100px%27%20width%20%3D%20%27100px%27%3E%3Ctext%20transform%20%3D%20%27translate(20%2C%20100)%20rotate(-45)%27%20fill%20%3D%20%27rgb(245%2C45%2C45)%27%20font-size%20%3D%20%2720%27%3E%20watermark%20%3C%2Ftext%3E%3C%2Fsvg%3E");
}

To print a background image using WebBrowser control I tried this post: How to print background image and styles in WebBrowser control. But it looks like it doesn't print my data-uri svc image because of the IE limitations.

How can I print watermark background Image in WebBrowser control?


Here is the alternative solution that I've tried.

I tried to print HTML converted to image silently in webbrowser, but it prints empty page. To do so I used HTMLRenderer is a nuget package. refereed to this answer.

public MemoryStream ConvertHtmlToImage(string html)
{
    Bitmap m_Bitmap = new Bitmap("image");
    HtmlRender.RenderGdiPlus(Graphics.FromImage(m_Bitmap),
                                           html);
    MemoryStream memoryStream = new MemoryStream();

    m_Bitmap.Save(memoryStream, System.Drawing.Imaging.ImageFormat.Png);
    return memoryStream;

}
MemoryStream HtmlImage = ConvertHtmlToImage(processedDocTest);
webBrowserTest = new System.Windows.Forms.WebBrowser();
webBrowserTest.DocumentStream = HtmlImage; //Assign the image as a stream 
private void btn_print_test_Click(object sender, EventArgs e)
{
    if (Common.TestPrinter != null && !string.IsNullOrEmpty(Common.TestPrinter))
    {
        SetupPage();
        SetDefaultPrinter(Common.TestPrinter);
    }
    PrinterSettings settings = new PrinterSettings();
    defaultPrinter = settings.PrinterName;

    if (Common.TestPrinter == defaultPrinter)
    {
        PrintTest();
    }
    else
    {
        ResetSetupPage();
        Environment.Exit(1);
    }
}
Reza Aghaei
  • 120,393
  • 18
  • 203
  • 398
Anyname Donotcare
  • 11,113
  • 66
  • 219
  • 392
  • Where's the code you use to print the image? i only see PrintTest(), and i assume that's to print a test page (perhaps an empty one)? – Glenn van Acker Nov 28 '19 at 12:25
  • The linked post shows how you can successfully have a silent printing using a WebBropwser control. As it's already discussed in the comments of the linked post if you load https://www.bing.com (which contains background images), you will see it works as expected. Is it a follow up for the linked question? – Reza Aghaei Nov 28 '19 at 14:07
  • @RezaAghaei It's a follow up question, after I realized that the IE is limited to print `SVG` as a background image, I decided to convert the whole html document to image to print it silently so that I can overcome this limitation. so for the library I edit the question to refer to it, and U have helped me a lot in previous questions related to this context(I'm so grateful), so the html is a simple html doc contains `svg` as a background for the body(water mark) in the related question and I converted the whole doc to image so that i can print it. – Anyname Donotcare Nov 28 '19 at 15:41

2 Answers2

3

Internet Explorer shows the svg data uri background images well, but doesn't work well when it comes to printing svg data uri background images.

To have a hasslefree printing of background images, you can use a svg image instead of data uri or if for some reason, you want to use data uri, then use a transparent png data uri as background image.

In this post, I assume you want to generate transparent png image of a text at run-time and use the image as background image of a page using data uri format.

Here are building blocks of the answer:

  • Create transparent image from text at run-time
  • Convert image to data uri
  • Enable printing backgrounds in WebBrowser control
  • Print WebBrowser control without showing Print Dialog

To print like this:

enter image description here

Create transparent image from text at run-time

This method accepts a text, font, color of text and size of the image and then generates an image:

public Image CreateWatermarkImage(string text, Font font, Color color, Size size)
{
    var bm = new Bitmap(size.Width, size.Height, PixelFormat.Format32bppArgb);
    using (var g = Graphics.FromImage(bm))
    {
        g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias;
        g.RotateTransform(45);
        var format = new StringFormat();
        format.Alignment = StringAlignment.Center;
        using (var brush = new SolidBrush(color))
            g.DrawString(text, font, brush, new Rectangle(Point.Empty, size), format);
    }
    return bm;
}

Convert image to data uri

This method gets an image and convert it to data uri:

public static string GetDataURL(Image image)
{
    var bytes = (byte[])new ImageConverter().ConvertTo(image, typeof(byte[]));
    return $"data:image/png;base64,{Convert.ToBase64String(bytes)}";
}

Enable printing backgrounds in WebBrowser control

As I already explained in my linked answer about Print Background Image in WebBrowser you need to change a setting in Registry. (Read the linked post for more details.)

public void EnablePrintBackground(bool value)
{
    using (var key = Microsoft.Win32.Registry.CurrentUser.OpenSubKey(
        @"Software\Microsoft\Internet Explorer\PageSetup", true))
    {
        key.SetValue("Print_Background", value ? "yes" : "no",
            Microsoft.Win32.RegistryValueKind.String);
        key.Close();
    }
}

Print WebBrowser control without showing Print Dialog

As I already explained in another post about Print WebBrowser control without showing Print Dialog, just use Print() method of the web browser control. (You can read more details in the linked post.)

webBrowser1.Print();

Put all things together in an Example

Here I put all things together to print a html having a data uri transparent background image at run-time:

private void Form1_Load(object sender, EventArgs e)
{
    var dataURL = "";
    using (var image = CreateWatermarkImage("Watermark!",
        new Font("Arial", 16, FontStyle.Bold), Color.Red, new Size(150, 150)))
    {
        dataURL = GetDataURL(image);
    }
    var html = $@"
        <html>
            <head>
                <style>body {{background-image: url(""{dataURL}"");}}</style>
            </head>
            <body>
                <h1>Lorem ipsum dolor sit amet</h1> 
                consectetur adipiscing elit, 
                sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. 
                Ut enim ad minim veniam, quis nostrud exercitation ullamco 
                laboris nisi ut aliquip ex ea commodo consequat. 
                Duis aute irure dolor in reprehenderit in voluptate velit 
                esse cillum dolore eu fugiat nulla pariatur. Excepteur sint 
                occaecat cupidatat non proident, sunt in culpa qui officia 
                deserunt mollit anim id est laborum.
            </body>
        </html>";
    webBrowser1.DocumentText = html;
    webBrowser1.DocumentCompleted += (obj, args) =>
    {
        EnablePrintBackground(true);
        webBrowser1.Print();
    };
}

And here is the result:

enter image description here

Reza Aghaei
  • 120,393
  • 18
  • 203
  • 398
-1

Use this Code:

public void ConvertHtmlToImage(string html)
{
Bitmap m_Bitmap = new Bitmap(400, 600);
PointF point = new PointF(0, 0);
SizeF maxSize = new System.Drawing.SizeF(500, 500);
HtmlRenderer.HtmlRender.Render(Graphics.FromImage(m_Bitmap),html,
                                        point, maxSize);

m_Bitmap.Save(@"C:\MyHtml.png", ImageFormat.Png);
}
RezaGhahari
  • 405
  • 3
  • 9