In many cases, HTML documents are used to create templates for various reports with subsequent conversion into PDF docs. The Canvas API is a powerful tool for creating images and it can also be used to place graphics in PDF documents. This API is used by writing JS-scripts that can access the canvas area through a full set of drawing functions, thus allowing for dynamically generated graphics.
Aspose.HTML supports two methods of accessing to canvas elements:
- via JavaScript code - this is a traditional method and it is preferable when we use standard HTML docs;
- via Aspose.HTML API - this method is more convenient for creating in-memory HTML docs;
Since the first method is very popular, we will consider only a small example of its usage.
private static void ConvertCanvastoPdf() | |
{ | |
const string content = | |
"<!DOCTYPE html><html><head><title>A Simple Canvas Example</title><style>body{background: #aabbcc;}" + | |
"#canvas{margin: 10px;padding: 10px;background: #ffffff;border: 3px groove #aabbcc;}</style></head>" + | |
"<body>" + | |
"<canvas id='canvas' width='320' height='240'> Canvas not supported</canvas>" + | |
"<script>" + | |
"var canvas=document.getElementById('canvas');" + | |
"var context=canvas.getContext('2d');" + | |
"context.font='20pt Arial';context.fillStyle='navy';context.strokeStyle='blue';" + | |
"context.fillText('Hello Canvas', 30, 30);" + | |
"context.strokeText('Hello Canvas', 30, 30);" + | |
"</script>" + | |
"</body></html>"; | |
var document = new Aspose.Html.HTMLDocument(content, string.Empty); | |
GeneratePdfDoc(document, OutputFile); | |
} |
As has been said before, we will use the Aspose.HTML API in the second method. This method has some differences from the previous, mainly because of the features of the .NET platform, but the main concept is the same.
As an example, consider the following problem: suppose that we need to generate a report for one (or several) images on which we need to mark certain regions (faces, animals, etc) and add it with text. Thus, our solution will consist of the following steps:
- Generate a template;
- Get details about the image (from external service);
- Generate report as HTML document;
- Convert HTML document to PDF one.
private static void CanvasToPdfDemo() | |
{ | |
var document = CreateHtmlTemplate(); | |
var faces = MakeAnalysisRequest(ImageFilePath).Result; | |
GenerateReport(document, faces); | |
GeneratePdfDoc(document, OutputFile); | |
} |
Step 1 is pretty straightforward:
private static HTMLDocument CreateHtmlTemplate() | |
{ | |
var document = new Aspose.Html.HTMLDocument(); | |
document.AppendChild(document.CreateDocumentType("html", "", "", "")); | |
document.DocumentElement.SetAttribute("lang", "en"); | |
document.Title = "Face detection report"; | |
var head = document.GetElementsByTagName("head")[0]; | |
var metaCharSet = (HTMLMetaElement)document.CreateElement("meta"); | |
metaCharSet.SetAttribute("charset", "utf-8"); | |
var metaViewPort = (HTMLMetaElement)document.CreateElement("meta"); | |
metaViewPort.Name = "viewport"; | |
metaViewPort.Content = "width=device-width, initial-scale=1"; | |
head.AppendChild(metaCharSet); | |
head.AppendChild(metaViewPort); | |
var header1 = (HTMLHeadingElement)document.CreateElement("h1"); | |
header1.TextContent = "Detection report"; | |
document.DocumentElement.LastElementChild.AppendChild(header1); | |
var canvas = (HTMLCanvasElement)document.CreateElement("canvas"); | |
canvas.Style.CSSText = "border: 1px solid black"; | |
document.DocumentElement.LastElementChild.AppendChild(canvas); | |
return document; | |
} |
In step 2, we will use Microsoft Cognitive Services (Face API). You may learn more about this service on Microsoft Docs. In short, we call the REST API and get the result with a set of detected faces with additional info.
/// <summary> | |
/// Gets the analysis of the specified image by using the Face REST API. | |
/// </summary> | |
/// <param name="imageFilePath">The image file.</param> | |
private static async Task<Microsoft.ProjectOxford.Face.Contract.Face[]> MakeAnalysisRequest(string imageFilePath) | |
{ | |
const string subscriptionKey = "*************"; | |
const string uriBase = "https://westcentralus.api.cognitive.microsoft.com/face/v1.0"; | |
var faceServiceClient = new FaceServiceClient(subscriptionKey, uriBase); | |
return await faceServiceClient.DetectAsync(imageFilePath, false, true, | |
new[] { FaceAttributeType.Gender, FaceAttributeType.Age }); | |
} | |
} | |
} |
Now we can add the data to report: modify canvas
and add p
element after the canvas
. In order to modify canvas
, we need to get the context
of this element and make the drawing.
var imageObj = (HTMLImageElement)document.CreateElement("img"); | |
imageObj.Src = ImageFilePath; | |
var canvas = (HTMLCanvasElement)document.GetElementsByTagName("canvas")[0]; | |
canvas.Width = canvasWidth; | |
canvas.Height = canvasHeight; | |
var context = (ICanvasRenderingContext2D)canvas.GetContext("2d"); | |
context.ClearRect(0, 0, canvasWidth, canvasHeight); | |
context.DrawImage(imageObj, 0, 0); | |
context.BeginPath(); | |
context.LineWidth = 2.0; |
The resulting object from the previous step is an array, which contains rectangles, that describes face locations on the image. So, we run the loop and draw the rectangles in the manner as in JavaScript code. At the last, we add details as p
elements below canvas
.
private static void GenerateReport(HTMLDocument document, Face[] faces) | |
{ | |
const int canvasWidth = 640; | |
const int canvasHeight = 480; | |
var colors = new[] { | |
"Red", "Cyan", "Orange", "Green", "Blue", "Purple", "Black", "Aqua", "Olive", "Navy", "Teal", | |
"Maroon", "Gray", "Beige", "MediumSlateBlue", "Aquamarine", "LightSalmon", "Gold", "LightSeaGreen", | |
"Violet", "Chartreuse", "LightSalmon", "MediumSlateBlue" | |
}; | |
var imageObj = (HTMLImageElement)document.CreateElement("img"); | |
{ | |
imageObj.Src = ImageFilePath; | |
var canvas = (HTMLCanvasElement)document.GetElementsByTagName("canvas")[0]; | |
canvas.Width = canvasWidth; | |
canvas.Height = canvasHeight; | |
var context = (ICanvasRenderingContext2D)canvas.GetContext("2d"); | |
context.ClearRect(0, 0, canvasWidth, canvasHeight); | |
context.DrawImage(imageObj, 0, 0); | |
context.BeginPath(); | |
context.LineWidth = 2.0; | |
for (var i = 0; i < faces.Length; i++) | |
{ | |
context.StrokeStyle = colors[i % 24]; | |
context.StrokeRect( | |
faces[i].FaceRectangle.Left, | |
faces[i].FaceRectangle.Top, | |
faces[i].FaceRectangle.Width, | |
faces[i].FaceRectangle.Height); | |
context.Stroke(); | |
var paragraph = (HTMLParagraphElement)document.CreateElement("p"); | |
paragraph.TextContent = $"{colors[i]} - {faces[i].FaceAttributes.Age}, {faces[i].FaceAttributes.Gender}"; | |
document.DocumentElement.LastElementChild.AppendChild(paragraph); | |
} | |
} | |
} |
Оbtained HTML document we can easily convert to PDF.
private static void GeneratePdfDoc(HTMLDocument document, string outputfile) | |
{ | |
var options = new PdfRenderingOptions(); | |
options.PageSetup.AnyPage.Margin.Top = Unit.FromMillimeters(20); | |
options.PageSetup.AnyPage.Margin.Bottom = Unit.FromMillimeters(20); | |
options.PageSetup.AnyPage.Margin.Left = Unit.FromMillimeters(20); | |
options.PageSetup.AnyPage.Margin.Right = Unit.FromMillimeters(20); | |
Console.WriteLine("Render PDF file started..."); | |
var device = new PdfDevice(options, outputfile); | |
var renderer = new HtmlRenderer(); | |
renderer.Render(device, document); | |
Console.WriteLine("Render PDF file finished."); | |
} |
You can see full example here:
using System; | |
using System.Threading.Tasks; | |
using Aspose.Html; | |
using Aspose.Html.Dom.Canvas; | |
using Aspose.Html.Drawing; | |
using Aspose.Html.Rendering; | |
using Aspose.Html.Rendering.Pdf; | |
using Microsoft.ProjectOxford.Face; | |
using Microsoft.ProjectOxford.Face.Contract; | |
namespace Canvas | |
{ | |
class Program | |
{ | |
private const string ImageFilePath = "http://universe.bits-pilani.ac.in/Uploads/Pilani/pilanibiologicalScienceadmin/Gallery/2015-1-5--14-36-35-944_6.JPG"; | |
private const string OutputFile = @"C:\aspose\pdf\output01.pdf"; | |
private static void Main() | |
{ | |
ConvertCanvastoPdf(); | |
//ConvertCanvastoPdf2(); | |
CanvasToPdfDemo(); | |
} | |
private static void ConvertCanvastoPdf() | |
{ | |
const string content = "<!DOCTYPE html><html><head><title>A Simple Canvas Example</title><style>body{background: #aabbcc;}" + | |
"#canvas{margin: 10px;padding: 10px;background: #ffffff;border: 3px groove #aabbcc;}</style></head>" + | |
"<body>" + | |
"<canvas id='canvas' width='320' height='240'> Canvas not supported</canvas>" + | |
"<script>" + | |
"var canvas=document.getElementById('canvas');" + | |
"var context=canvas.getContext('2d');" + | |
"context.font='20pt Arial';context.fillStyle='navy';context.strokeStyle='blue';" + | |
"context.fillText('Hello Canvas', 30, 30);" + | |
"context.strokeText('Hello Canvas', 30, 30);" + | |
"</script>" + | |
"</body></html>"; | |
var document = new HTMLDocument(content, string.Empty); | |
GeneratePdfDoc(document, OutputFile); | |
} | |
private static void CanvasToPdfDemo() | |
{ | |
var document = CreateHtmlTemplate(); | |
var faces = MakeAnalysisRequest(ImageFilePath).Result; | |
GenerateReport(document, faces); | |
GeneratePdfDoc(document, OutputFile); | |
} | |
private static void GenerateReport(HTMLDocument document, Face[] faces) | |
{ | |
const int canvasWidth = 640; | |
const int canvasHeight = 480; | |
var colors = new[] { | |
"Red", "Cyan", "Orange", "Green", "Blue", "Purple", "Black", "Aqua", "Olive", "Navy", "Teal", | |
"Maroon", "Gray", "Beige", "MediumSlateBlue", "Aquamarine", "LightSalmon", "Gold", "LightSeaGreen", | |
"Violet", "Chartreuse", "LightSalmon", "MediumSlateBlue" | |
}; | |
var imageObj = (HTMLImageElement)document.CreateElement("img"); | |
imageObj.Src = ImageFilePath; | |
var canvas = (HTMLCanvasElement)document.GetElementsByTagName("canvas")[0]; | |
canvas.Width = canvasWidth; | |
canvas.Height = canvasHeight; | |
var context = (ICanvasRenderingContext2D)canvas.GetContext("2d"); | |
context.ClearRect(0, 0, canvasWidth, canvasHeight); | |
context.DrawImage(imageObj, 0, 0); | |
context.BeginPath(); | |
context.LineWidth = 2.0; | |
for (var i = 0; i < faces.Length; i++) | |
{ | |
context.StrokeStyle = colors[i % 24]; | |
context.StrokeRect( | |
faces[i].FaceRectangle.Left, | |
faces[i].FaceRectangle.Top, | |
faces[i].FaceRectangle.Width, | |
faces[i].FaceRectangle.Height); | |
context.Stroke(); | |
var paragraph = (HTMLParagraphElement)document.CreateElement("p"); | |
paragraph.TextContent = $"{colors[i]} - {faces[i].FaceAttributes.Age}, {faces[i].FaceAttributes.Gender}"; | |
document.DocumentElement.LastElementChild.AppendChild(paragraph); | |
} | |
} | |
private static void GeneratePdfDoc(HTMLDocument document, string outputfile) | |
{ | |
var options = new PdfRenderingOptions(); | |
options.PageSetup.AnyPage.Margin.Top = Unit.FromMillimeters(20); | |
options.PageSetup.AnyPage.Margin.Bottom = Unit.FromMillimeters(20); | |
options.PageSetup.AnyPage.Margin.Left = Unit.FromMillimeters(20); | |
options.PageSetup.AnyPage.Margin.Right = Unit.FromMillimeters(20); | |
Console.WriteLine("Render PDF file started..."); | |
var device = new PdfDevice(options, outputfile); | |
var renderer = new HtmlRenderer(); | |
renderer.Render(device, document); | |
Console.WriteLine("Render PDF file finished."); | |
} | |
private static HTMLDocument CreateHtmlTemplate() | |
{ | |
var document = new HTMLDocument(); | |
document.AppendChild(document.CreateDocumentType("html", "", "", "")); | |
document.DocumentElement.SetAttribute("lang", "en"); | |
document.Title = "Face detection report"; | |
var head = document.GetElementsByTagName("head")[0]; | |
var metaCharSet = (HTMLMetaElement)document.CreateElement("meta"); | |
metaCharSet.SetAttribute("charset", "utf-8"); | |
var metaViewPort = (HTMLMetaElement)document.CreateElement("meta"); | |
metaViewPort.Name = "viewport"; | |
metaViewPort.Content = "width=device-width, initial-scale=1"; | |
head.AppendChild(metaCharSet); | |
head.AppendChild(metaViewPort); | |
var header1 = (HTMLHeadingElement)document.CreateElement("h1"); | |
header1.TextContent = "Detection report"; | |
document.DocumentElement.LastElementChild.AppendChild(header1); | |
var canvas = (HTMLCanvasElement)document.CreateElement("canvas"); | |
canvas.Style.CSSText = "border: 1px solid black"; | |
document.DocumentElement.LastElementChild.AppendChild(canvas); | |
return document; | |
} | |
/// <summary> | |
/// Gets the analysis of the specified image by using the Face REST API. | |
/// </summary> | |
/// <param name="imageFilePath">The image file.</param> | |
private static async Task<Face[]> MakeAnalysisRequest(string imageFilePath) | |
{ | |
const string subscriptionKey = "<key>"; | |
const string uriBase = "https://westcentralus.api.cognitive.microsoft.com/face/v1.0"; | |
var faceServiceClient = new FaceServiceClient(subscriptionKey, uriBase); | |
return await faceServiceClient.DetectAsync(imageFilePath, false, true, | |
new[] { FaceAttributeType.Gender, FaceAttributeType.Age }); | |
} | |
} | |
} |
Top comments (1)
Pdf must be in form of vector not image