Hi,
I tried using the method that was suggested but it does not create any visible outputs.
Here is the code.
using System;
using System.Drawing;
using System.IO;
using Aspose.Words.Drawing;
using Aspose.Words.Saving;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace Aspose.Words.Test
{
[TestClass]
public class TableTestSuite
{
[TestMethod]
public void TableToImageTest()
{
Document document = new Document();
DocumentBuilder builder = new DocumentBuilder(document);
// Create table with 3 rows and 2 cells in each row.
Tables.Table table = new Tables.Table(document);
Tables.Row row1 = new Tables.Row(document);
Tables.Row row2 = new Tables.Row(document);
Tables.Row row3 = new Tables.Row(document);
table.Rows.Add(row1);
table.Rows.Add(row2);
table.Rows.Add(row3);
Tables.Cell cell1 = new Tables.Cell(document);
Tables.Cell cell2 = new Tables.Cell(document);
row1.Cells.Add(cell1);
row1.Cells.Add(cell2);
Tables.Cell cell3 = new Tables.Cell(document);
Tables.Cell cell4 = new Tables.Cell(document);
row2.Cells.Add(cell3);
row2.Cells.Add(cell4);
Tables.Cell cell5 = new Tables.Cell(document);
Tables.Cell cell6 = new Tables.Cell(document);
row3.Cells.Add(cell5);
row3.Cells.Add(cell6);
// Set cell border values.
ApplyBorders(cell1);
ApplyBorders(cell2);
ApplyBorders(cell3);
ApplyBorders(cell4);
ApplyBorders(cell5);
ApplyBorders(cell6);
// Add text into cell1 and cell 2
Paragraph paragraph1 = new Paragraph(document);
paragraph1.Runs.Add(new Run(document, "Hello World1"));
cell1.Paragraphs.Add(paragraph1);
Paragraph paragraph2 = new Paragraph(document);
paragraph2.Runs.Add(new Run(document, "Hello World2"));
cell2.Paragraphs.Add(paragraph2);
// Insert image rendered from table.
builder.InsertImage(RenderNode(table, null));
document.Save("C:\\Code\\SHL.ReportEngine.DocumentEngine\\Statements\\Tests\\Outputs\\TableToImageTest.doc");
}
private void ApplyBorders(Tables.Cell cell)
{
cell.CellFormat.Borders.Top.Color = Color.Black;
cell.CellFormat.Borders.Right.Color = Color.Black;
cell.CellFormat.Borders.Left.Color = Color.Black;
cell.CellFormat.Borders.Bottom.Color = Color.Black;
cell.CellFormat.Borders.LineWidth = 1;
cell.CellFormat.Borders.LineStyle = LineStyle.Single;
}
///
/// Renders any node in a document to the path specified using the image save options.
///
public static Image RenderNode(Node node, ImageSaveOptions imageOptions)
{
// Run some argument checks.
if (node == null)
throw new ArgumentException("Node cannot be null");
// If no image options are supplied, create default options.
if (imageOptions == null)
imageOptions = new ImageSaveOptions(SaveFormat.Png);
// Store the paper color to be used on the final image and change to transparent.
// This will cause any content around the rendered node to be removed later on.
Color savePaperColor = imageOptions.PaperColor;
imageOptions.PaperColor = Color.Transparent;
// There a bug which affects the cache of a cloned node. To avoid this we instead clone the entire document including all nodes,
// find the matching node in the cloned document and render that instead.
Document doc = (Document)node.Document.Clone(true);
node = doc.GetChild(NodeType.Any, node.Document.GetChildNodes(NodeType.Any, true).IndexOf(node), true);
// Create a temporary shape to store the target node in. This shape will be rendered to retrieve
// the rendered content of the node.
Shape shape = new Shape(doc, ShapeType.TextBox);
Section parentSection = (Section)node.GetAncestor(NodeType.Section);
// Assume that the node cannot be larger than the page in size.
shape.Width = parentSection.PageSetup.PageWidth;
shape.Height = parentSection.PageSetup.PageHeight;
shape.FillColor = Color.Transparent; // We must make the shape and paper color transparent.
// Don't draw a surronding line on the shape.
shape.Stroked = false;
Node currentNode = node;
// If the node contains block level nodes then just add a copy of these nodes to the shape.
if (currentNode is InlineStory || currentNode is Story)
{
CompositeNode composite = (CompositeNode)currentNode;
foreach (Node childNode in composite.ChildNodes)
{
shape.AppendChild(childNode.Clone(true));
}
}
else
{
// Move up through the DOM until we find node which is suitable to insert into a Shape (a node with a parent can contain paragraph, tables the same as a shape).
// Each parent node is cloned on the way up so even a descendant node passed to this method can be rendered.
// Since we are working with the actual nodes of the document we need to clone the target node into the temporary shape.
while (!(currentNode.ParentNode is InlineStory || currentNode.ParentNode is Story || currentNode.ParentNode is ShapeBase || currentNode.NodeType == NodeType.Paragraph))
{
CompositeNode parent = (CompositeNode)currentNode.ParentNode.Clone(false);
currentNode = currentNode.ParentNode;
parent.AppendChild(node.Clone(true));
node = parent; // Store this new node to be inserted into the shape.
}
// Add the node to the shape.
shape.AppendChild(node.Clone(true));
}
// We must add the shape to the document tree to have it rendered.
parentSection.Body.FirstParagraph.AppendChild(shape);
// Render the shape to stream so we can take advantage of the effects of the ImageSaveOptions class.
// Retrieve the rendered image and remove the shape from the document.
MemoryStream stream = new MemoryStream();
shape.GetShapeRenderer().Save("C:\\Code\\SHL.ReportEngine.DocumentEngine\\Statements\\Tests\\Outputs\\tableimage.png", imageOptions);
shape.GetShapeRenderer().Save(stream, imageOptions);
shape.Remove();
Bitmap croppedImage;
// Load the image into a new bitmap.
using (Bitmap renderedImage = new Bitmap(stream))
{
// Extract the actual content of the image by cropping transparent space around
// the rendered shape.
Rectangle cropRectangle = FindBoundingBoxAroundNode(renderedImage);
croppedImage = new Bitmap(cropRectangle.Width, cropRectangle.Height);
croppedImage.SetResolution(imageOptions.Resolution, imageOptions.Resolution);
// Create the final image with the proper background color.
using (Graphics g = Graphics.FromImage(croppedImage))
{
g.Clear(savePaperColor);
g.DrawImage(renderedImage, new Rectangle(0, 0, croppedImage.Width, croppedImage.Height), cropRectangle.X, cropRectangle.Y, cropRectangle.Width, cropRectangle.Height, GraphicsUnit.Pixel);
}
}
return croppedImage;
}
///
/// Finds the minimum bounding box around non-transparent pixels in a Bitmap.
///
public static Rectangle FindBoundingBoxAroundNode(Bitmap originalBitmap)
{
Point min = new Point(int.MaxValue, int.MaxValue);
Point max = new Point(int.MinValue, int.MinValue);
for (int x = 0; x < originalBitmap.Width; ++x)
{
for (int y = 0; y < originalBitmap.Height; ++y)
{
// Note that you can speed up this part of the algorithm by using LockBits and unsafe code instead of GetPixel.
Color pixelColor = originalBitmap.GetPixel(x, y);
// For each pixel that is not transparent calculate the bounding box around it.
if (pixelColor.ToArgb() != Color.Empty.ToArgb())
{
min.X = System.Math.Min(x, min.X);
min.Y = System.Math.Min(y, min.Y);
max.X = System.Math.Max(x, max.X);
max.Y = System.Math.Max(y, max.Y);
}
}
}
// Add one pixel to the width and height to avoid clipping.
return new Rectangle(min.X, min.Y, (max.X - min.X) + 1, (max.Y - min.Y) + 1);
}
}
}
Thanks.