How to create a table using PDFsharp? - vb.net

Just started using PDFsharp and it works fine, but now I want to create tables in my PDF, but tried other sources and found nothing.
So far I know how to use graph.drawString().

I could not find any clear and simple example of a basic table-template.
pdfSharp is a very powerful but extremely low level library, so it's difficult to draw rectangles and text with fixed positions. Anyway, here is a little complete example that shows how to draw a table:
protected void ExportGraf_Click(object sender, EventArgs e)
{
PdfDocument document = new PdfDocument();
document.Info.Title = "Table Example";
for (int p=0; p<1; p++)
{
// Page Options
PdfPage pdfPage = document.AddPage();
pdfPage.Height = 842;//842
pdfPage.Width = 590;
// Get an XGraphics object for drawing
XGraphics graph = XGraphics.FromPdfPage(pdfPage);
// Text format
XStringFormat format = new XStringFormat();
format.LineAlignment = XLineAlignment.Near;
format.Alignment = XStringAlignment.Near;
var tf = new XTextFormatter(graph);
XFont fontParagraph = new XFont("Verdana", 8, XFontStyle.Regular);
// Row elements
int el1_width = 80;
int el2_width = 380;
// page structure options
double lineHeight = 20;
int marginLeft = 20;
int marginTop = 20;
int el_height = 30;
int rect_height = 17;
int interLine_X_1 = 2;
int interLine_X_2 = 2 * interLine_X_1;
int offSetX_1 = el1_width;
int offSetX_2 = el1_width + el2_width;
XSolidBrush rect_style1 = new XSolidBrush(XColors.LightGray);
XSolidBrush rect_style2 = new XSolidBrush(XColors.DarkGreen);
XSolidBrush rect_style3= new XSolidBrush(XColors.Red);
for (int i = 0; i < 30; i++)
{
double dist_Y = lineHeight * (i + 1);
double dist_Y2 = dist_Y - 2;
// header della G
if (i == 0)
{
graph.DrawRectangle(rect_style2, marginLeft, marginTop, pdfPage.Width-2* marginLeft, rect_height);
tf.DrawString("column1", fontParagraph, XBrushes.White,
new XRect(marginLeft, marginTop, el1_width, el_height), format);
tf.DrawString("column2", fontParagraph, XBrushes.White,
new XRect(marginLeft + offSetX_1 + interLine_X_1, marginTop , el2_width, el_height), format);
tf.DrawString("column3", fontParagraph, XBrushes.White,
new XRect(marginLeft + offSetX_2 + 2 * interLine_X_2, marginTop, el1_width, el_height), format);
// stampo il primo elemento insieme all'header
graph.DrawRectangle(rect_style1, marginLeft, dist_Y2 + marginTop, el1_width, rect_height);
tf.DrawString("text1", fontParagraph, XBrushes.Black,
new XRect(marginLeft, dist_Y + marginTop, el1_width, el_height), format);
//ELEMENT 2 - BIG 380
graph.DrawRectangle(rect_style1, marginLeft + offSetX_1 + interLine_X_1, dist_Y2 + marginTop, el2_width, rect_height);
tf.DrawString(
"text2",
fontParagraph,
XBrushes.Black,
new XRect(marginLeft + offSetX_1 + interLine_X_1, dist_Y + marginTop, el2_width, el_height),
format);
//ELEMENT 3 - SMALL 80
graph.DrawRectangle(rect_style1, marginLeft + offSetX_2 + interLine_X_2, dist_Y2 + marginTop, el1_width, rect_height);
tf.DrawString(
"text3",
fontParagraph,
XBrushes.Black,
new XRect(marginLeft + offSetX_2 + 2 * interLine_X_2, dist_Y + marginTop, el1_width, el_height),
format);
}
else {
//if (i % 2 == 1)
//{
// graph.DrawRectangle(TextBackgroundBrush, marginLeft, lineY - 2 + marginTop, pdfPage.Width - marginLeft - marginRight, lineHeight - 2);
//}
//ELEMENT 1 - SMALL 80
graph.DrawRectangle(rect_style1, marginLeft, marginTop + dist_Y2, el1_width, rect_height);
tf.DrawString(
"text1",
fontParagraph,
XBrushes.Black,
new XRect(marginLeft, marginTop + dist_Y, el1_width, el_height),
format);
//ELEMENT 2 - BIG 380
graph.DrawRectangle(rect_style1, marginLeft + offSetX_1 + interLine_X_1 , dist_Y2 + marginTop, el2_width, rect_height);
tf.DrawString(
"text2",
fontParagraph,
XBrushes.Black,
new XRect(marginLeft + offSetX_1 + interLine_X_1, marginTop + dist_Y, el2_width, el_height),
format);
//ELEMENT 3 - SMALL 80
graph.DrawRectangle(rect_style1, marginLeft + offSetX_2 + interLine_X_2, dist_Y2 + marginTop, el1_width, rect_height);
tf.DrawString(
"text3",
fontParagraph,
XBrushes.Black,
new XRect(marginLeft + offSetX_2 + 2 *interLine_X_2, marginTop + dist_Y, el1_width, el_height),
format);
}
}
}
const string filename = "C:\\Users\\Desktop\\test\\HelloWorld.pdf";
document.Save(filename);
//byte[] bytes = null;
//using (MemoryStream stream = new MemoryStream())
//{
// document.Save(stream, true);
// bytes = stream.ToArray();
//}
//SendFileToResponse(bytes, "HelloWorld_test.pdf");
}
Notice you can print more pages within the document; just change the first "for".
It should render like this:
.

With PDFsharp: draw text, draw lines around it.
With MigraDoc (you already added that tag): add a Table to your document and add the columns, rows, and borders you need.
The MigraDoc samples that come with MigraDoc are all C#, but a VB.NET sample can be found on the forum.
VB.NET sample on official PDFsharp/MigraDoc forum:
http://forum.pdfsharp.net/viewtopic.php?f=8&t=3207
C# sample on official site that shows usage of tables:
http://pdfsharp.net/wiki/Invoice-sample.ashx

This example creates a table, but also shows you how to insert text, draw lines, squares, and set up margins. Still a work in progress.
//PdfSharpUtilities.cs
//*******************************************************************/
/* Usage example
private void buttonRunExample_Click(object sender, EventArgs e)
{
PdfSharpUtilities pdf = new PdfSharpUtilities("test.pdf", true);
pdf.drawSquare(new DPoint(0, 0), 3, 2, XBrushes.Purple);
pdf.addText("Username", new DPoint(0, 4.5), 16);
pdf.addText("Invoice", new DPoint(12.15, 1.5), 14);
pdf.addText("Account: 69696969", new DPoint(0, 6));
pdf.addText("Period: 2022-11", new DPoint(0, 7));
pdf.addText("E-mail: mail#gmail.com", new DPoint(0, 8));
pdf.addText("Inventory:", new DPoint(0, 10));
//Example table: to fill with example data leave contents = null
pdf.drawTable(0, 11, 15.7, 3, XBrushes.LightGray, null);
pdf.saveAndShow();
}*/
//******************************************************************/
public class PdfSharpUtilities
{
private double topMargin = 0;
private double leftMargin = 0;
private double rightMargin = 0;
private double bottomMargin = 0;
private double cm;
private PdfDocument document;
private PdfPage page;
private XGraphics gfx;
private XFont font;
private XPen pen;
private String outputPath;
public PdfSharpUtilities(String argOutputpath, Boolean argAddMarginGuides = false)
{
this.outputPath = argOutputpath;
//You’ll need a PDF document:
this.document = new PdfDocument();
//And you need a page:
this.page = document.AddPage();
this.page.Size = PageSize.Letter;
//Define how much a cm is in document's units
this.cm = new Interpolation().linearInterpolation(0, 0, 27.9, page.Height, 1);
Console.WriteLine("1 cm:" + cm);
//Drawing is done with an XGraphics object:
this.gfx = XGraphics.FromPdfPage(page);
this.font = new XFont("Arial", 12, XFontStyle.Bold);
this.pen = new XPen(XColors.Black, 0.5);
//Sugested margins
topMargin = 2.5 * cm;
leftMargin = 3 * cm;
rightMargin = page.Width - (3 * cm);
bottomMargin = page.Height - (2.5 * cm);
if (argAddMarginGuides)
{
gfx.DrawString("+", font, XBrushes.Black, rightMargin, topMargin);
gfx.DrawString("+", font, XBrushes.Black, leftMargin, topMargin);
gfx.DrawString("+", font, XBrushes.Black, rightMargin, bottomMargin);
gfx.DrawString("+", font, XBrushes.Black, leftMargin, bottomMargin);
}
Console.WriteLine("Page Width in cm:" + page.Width * cm);
Console.WriteLine("Page Height in cm:" + page.Height * cm);
Console.WriteLine("Top Margin in cm:" + topMargin);
Console.WriteLine("Left Margin in cm:" + leftMargin);
Console.WriteLine("Right Margin in cm:" + rightMargin);
Console.WriteLine("Bottom Margin in cm:" + bottomMargin);
}
public void drawTable(double initialPosX, double initialPosY, double width, double height, XBrush xbrush, List<String[]> contents = null)
{
drawSquare(new DPoint(initialPosX, initialPosY), width, height, xbrush);
if (contents == null)
{
contents = new List<String[]>();
contents.Add(new string[] { "Type", "Size", "Weight", "Stock", "Tax", "Price" });
contents.Add(new string[] { "Obo", "1", "45", "56", "16.00", "6.50" });
contents.Add(new string[] { "Crotolamo", "2", "72", "63", "16.00", "19.00" });
}
int columns = contents[0].Length;
int rows = contents.Count;
double distanceBetweenRows = height / rows;
double distanceBetweenColumns = width / columns;
/*******************************************************************/
// Draw the row lines
/*******************************************************************/
DPoint pointA = new DPoint(initialPosX, initialPosY);
DPoint pointB = new DPoint(initialPosX + width, initialPosY);
for (int i = 0; i <= rows; i++)
{
drawLine(pointA, pointB);
pointA.y = pointA.y + distanceBetweenRows;
pointB.y = pointB.y + distanceBetweenRows;
}
/*******************************************************************/
// Draw the column lines
/*******************************************************************/
pointA = new DPoint(initialPosX, initialPosY);
pointB = new DPoint(initialPosX, initialPosY + height);
for (int i = 0; i <= columns; i++)
{
drawLine(pointA, pointB);
pointA.x = pointA.x + distanceBetweenColumns;
pointB.x = pointB.x + distanceBetweenColumns;
}
/*******************************************************************/
// Insert text corresponding to each cell
/*******************************************************************/
pointA = new DPoint(initialPosX, initialPosY);
foreach (String[] rowDataArray in contents)
{
foreach (String cellText in rowDataArray)
{
this.gfx.DrawString(cellText, this.font, XBrushes.Black, new XRect(leftMargin + (pointA.x * cm), topMargin + (pointA.y * cm), distanceBetweenColumns * cm, distanceBetweenRows * cm), XStringFormats.Center);
pointA.x = pointA.x + distanceBetweenColumns;
}
pointA.x = initialPosX;
pointA.y = pointA.y + distanceBetweenRows;
}
}
public void addText(String text, DPoint xyStartingPosition, int size = 12)
{
this.gfx.DrawString(text, this.font, XBrushes.Black, leftMargin + (xyStartingPosition.x * cm), topMargin + (xyStartingPosition.y * cm));
}
public void drawSquare(DPoint xyStartingPosition, double width, double height, XBrush xbrush)
{
Console.WriteLine("Drawing square starting at: " + xyStartingPosition.x + "," + xyStartingPosition.y + " width: " + width + " height: " + height);
this.gfx.DrawRectangle(xbrush, new XRect(leftMargin + (xyStartingPosition.x * cm), topMargin + (xyStartingPosition.y * cm), (width * cm), (height * cm)));
}
public void drawLine(DPoint fromXyPosition, DPoint toXyPosition)
{
this.gfx.DrawLine(this.pen, leftMargin + (fromXyPosition.x * cm), topMargin + (fromXyPosition.y * cm), leftMargin + (toXyPosition.x * cm), topMargin + (toXyPosition.y * cm));
}
public void saveAndShow(Boolean argShowAfterSaving = true)
{
document.Save(this.outputPath);
if (argShowAfterSaving)
{
Process.Start(this.outputPath);
}
}
}
//DPoint.cs
public class DPoint
{
public double x { get; set; }
public double y { get; set; }
public DPoint(double x, double y)
{
this.x = x;
this.y = y;
}
}
//Interpolation.cs
public double linearInterpolation(double x0, double y0, double x1, double y1, double xd)
{
/*******************************************************************/
//
// x0 -------> y0
// given x -------> what is y?
// x1 -------> y1
/*******************************************************************/
return (y0 + ((y1 - y0) * ((xd - x0) / (x1 - x0))));
}

This work example, with MigroDoc. I changed a little from that example
static Table table;
static Document document;
static TextFrame addressFrame;
public static void Main()
{
const PdfFontEmbedding embedding = PdfFontEmbedding.Always;
PdfDocumentRenderer render = new PdfDocumentRenderer(true, embedding);
Document doc = CreateDocument();
render.Document = doc;
render.DocumentRenderer = render.DocumentRenderer;
render.RenderDocument();
render.PdfDocument.Save(#"D:\PDF1.pdf");
Process.Start(#"D:\PDF1.pdf");
}
public static Document CreateDocument()
{
// Create a new MigraDoc document
document = new Document();
document.Info.Title = "A sample invoice";
document.Info.Subject = "Demonstrates how to create an invoice.";
document.Info.Author = "Stefan Lange";
DefineStyles();
CreatePage();
FillContent();
return document;
}
static void DefineStyles()
{
// Get the predefined style Normal.
Style style = document.Styles["Normal"];
// Because all styles are derived from Normal, the next line changes the
// font of the whole document. Or, more exactly, it changes the font of
// all styles and paragraphs that do not redefine the font.
style.Font.Name = "Arial";
style = document.Styles[StyleNames.Header];
style.ParagraphFormat.AddTabStop("16cm", TabAlignment.Right);
style = document.Styles[StyleNames.Footer];
style.ParagraphFormat.AddTabStop("8cm", TabAlignment.Center);
// Create a new style called Table based on style Normal
style = document.Styles.AddStyle("Table", "Normal");
style.Font.Name = "Arial";
style.Font.Size = 9;
// Create a new style called Reference based on style Normal
style = document.Styles.AddStyle("Reference", "Normal");
style.ParagraphFormat.SpaceBefore = "5mm";
style.ParagraphFormat.SpaceAfter = "5mm";
style.ParagraphFormat.TabStops.AddTabStop("16cm", TabAlignment.Right);
}
static void CreatePage()
{
Section section = document.AddSection();
// Create footer
Paragraph paragraph = section.Footers.Primary.AddParagraph();
paragraph.AddText("PowerBooks Inc · Sample Street 42 · 56789 Cologne · Germany");
paragraph.Format.Font.Size = 9;
paragraph.Format.Alignment = ParagraphAlignment.Center;
// Create the text frame for the address
addressFrame = section.AddTextFrame();
addressFrame.Height = "3.0cm";
addressFrame.Width = "7.0cm";
addressFrame.Left = ShapePosition.Left;
addressFrame.RelativeHorizontal = RelativeHorizontal.Margin;
addressFrame.Top = "5.0cm";
addressFrame.RelativeVertical = RelativeVertical.Page;
// Put sender in address frame
paragraph = addressFrame.AddParagraph("PowerBooks Inc · Sample Street 42 · 56789 Cologne");
paragraph.Format.Font.Name = "Arial";
paragraph.Format.Font.Size = 7;
paragraph.Format.SpaceAfter = 3;
// Add the print date field
paragraph = section.AddParagraph();
paragraph.Format.SpaceBefore = "8cm";
paragraph.Style = "Reference";
paragraph.AddFormattedText("INVOICE");
paragraph.AddTab();
paragraph.AddText("Hello World");
paragraph.AddDateField("dd.MM.yyyy");
// Create the item table
table = section.AddTable();
table.Style = "Table";
table.Borders.Color = Colors.Black;
table.Borders.Width = 0.25;
table.Borders.Left.Width = 0.5;
table.Borders.Right.Width = 0.5;
table.Rows.LeftIndent = 0;
// Before you can add a row, you must define the columns
Column column = table.AddColumn("1cm");
column.Format.Alignment = ParagraphAlignment.Center;
column = table.AddColumn("2.5cm");
column.Format.Alignment = ParagraphAlignment.Right;
column = table.AddColumn("3cm");
column.Format.Alignment = ParagraphAlignment.Right;
column = table.AddColumn("3.5cm");
column.Format.Alignment = ParagraphAlignment.Right;
column = table.AddColumn("2cm");
column.Format.Alignment = ParagraphAlignment.Center;
column = table.AddColumn("4cm");
column.Format.Alignment = ParagraphAlignment.Right;
// Create the header of the table
Row row = table.AddRow();
row.HeadingFormat = true;
row.Format.Alignment = ParagraphAlignment.Center;
row.Format.Font.Bold = true;
row.Shading.Color = Colors.Red;
row.Cells[0].AddParagraph("Item");
row.Cells[0].Format.Font.Bold = false;
row.Cells[0].Format.Alignment = ParagraphAlignment.Left;
row.Cells[0].VerticalAlignment = VerticalAlignment.Bottom;
row.Cells[0].MergeDown = 1;
row.Cells[1].AddParagraph("Title and Author");
row.Cells[1].Format.Alignment = ParagraphAlignment.Left;
row.Cells[1].MergeRight = 3;
row.Cells[5].AddParagraph("Extended Price");
row.Cells[5].Format.Alignment = ParagraphAlignment.Left;
row.Cells[5].VerticalAlignment = VerticalAlignment.Bottom;
row.Cells[5].MergeDown = 0;
row = table.AddRow();
row.HeadingFormat = true;
row.Format.Alignment = ParagraphAlignment.Center;
row.Format.Font.Bold = true;
row.Shading.Color = Colors.Blue;
row.Cells[1].AddParagraph("Quantity");
row.Cells[1].Format.Alignment = ParagraphAlignment.Left;
row.Cells[2].AddParagraph("Unit Price");
row.Cells[2].Format.Alignment = ParagraphAlignment.Left;
row.Cells[3].AddParagraph("Discount (%)");
row.Cells[3].Format.Alignment = ParagraphAlignment.Left;
row.Cells[4].AddParagraph("Taxable");
row.Cells[4].Format.Alignment = ParagraphAlignment.Left;
table.SetEdge(0, 0, 6, 2, Edge.Box, BorderStyle.Single, 0.75, Color.Empty);
}
static void FillContent()
{
Paragraph paragraph = addressFrame.AddParagraph();
// Iterate the invoice items
double totalExtendedPrice = 0;
double quantity = 200;
double price = 40;
double discount = 5;
for (int i = 0; i < 10; i++)
{
// Each item fills two rows
Row row1 = table.AddRow();
Row row2 = table.AddRow();
row1.TopPadding = 1.5;
row1.Cells[0].Shading.Color = Colors.Gray;
row1.Cells[0].VerticalAlignment = VerticalAlignment.Center;
row1.Cells[0].MergeDown = 1;
row1.Cells[1].Format.Alignment = ParagraphAlignment.Left;
row1.Cells[1].MergeRight = 3;
row1.Cells[5].Shading.Color = Colors.Gray;
row1.Cells[5].MergeDown = 1;
row1.Cells[0].AddParagraph("Hello World 300");
paragraph = row1.Cells[1].AddParagraph();
paragraph.AddFormattedText("Hello World 234", TextFormat.Bold);
paragraph.AddFormattedText(" by ", TextFormat.Italic);
paragraph.AddText("Hello World 200");
row2.Cells[1].AddParagraph("Hello World 125");
row2.Cells[2].AddParagraph(price.ToString("0.00") + " €");
row2.Cells[3].AddParagraph(discount.ToString("0.0"));
row2.Cells[4].AddParagraph();
row2.Cells[5].AddParagraph(price.ToString("0.00"));
double extendedPrice = quantity * price;
extendedPrice = extendedPrice * (100 - discount) / 100;
row1.Cells[5].AddParagraph(extendedPrice.ToString("0.00") + " €");
row1.Cells[5].VerticalAlignment = VerticalAlignment.Bottom;
totalExtendedPrice += extendedPrice;
table.SetEdge(0, table.Rows.Count - 2, 6, 2, Edge.Box, BorderStyle.Single, 0.75);
}
}

Related

How to use PDF Sharp objects in my Migradoc document

I have an application that generates PDFs using the MigraDoc framework, however I have a requirement to add in a text driven watermark. I have found some examples of this being done using PDF Sharp here, however I just cant seem t be able to figure out how this will integrate with my Migradoc Document() object I am rendering.
I have the following code:
public byte[] render()
{
PdfDocument document = new PdfDocument();
CreateWaterMarks(document);
// *****************************
PdfDocumentRenderer renderer = new PdfDocumentRenderer(true);
renderer.Document = this.document;
renderer.RenderDocument();
byte[] pdfContents = null;
using (MemoryStream stream = new MemoryStream())
{
renderer.PdfDocument.Save(stream, true);
pdfContents = stream.ToArray();
}
return pdfContents;
}
This method is what is called to render the MigraDoc document and pass it out as a byte array. The second line of code in here calls the following method which is not doing what I am looking for:
void CreateWaterMarks(PdfDocument document)
{
PdfPage page = document.AddPage();
Document doc = this.document;
MigraDoc.Rendering.DocumentRenderer docRenderer = new DocumentRenderer(doc);
docRenderer.PrepareDocument();
XRect A4Rect = new XRect(0, 0, pageActiveWidth, pageActiveHeight);
int pageCount = docRenderer.FormattedDocument.PageCount;
for (int idx = 0; idx < pageCount; idx++)
{
XFont font = new XFont("Verdana", 13, XFontStyle.Bold);
XGraphics gfx = XGraphics.FromPdfPage(page, XGraphicsPdfPageOptions.Prepend);
XSize size = gfx.MeasureString("Watermark", font);
gfx.TranslateTransform(pageActiveWidth / 2, pageActiveHeight / 2);
gfx.RotateTransform(-Math.Atan(pageActiveHeight / pageActiveWidth) * 180 / Math.PI);
gfx.TranslateTransform(-pageActiveWidth / 2, -pageActiveHeight / 2);
XStringFormat format = new XStringFormat();
format.Alignment = XStringAlignment.Near;
format.LineAlignment = XLineAlignment.Near;
XBrush brush = new XSolidBrush(XColor.FromArgb(128, 255, 0, 0));
gfx.DrawString("Watermark", font, brush, new XPoint((pageActiveWidth - size.Width) / 2, (pageActiveHeight - size.Height) / 2), format);
docRenderer.RenderPage(gfx, idx + 1);
}
}
I was hoping that this would magically make these PDFSharp watermarks appear but alas I get nothing!
I have this working using the following code:
public byte[] render()
{
PdfDocumentRenderer renderer = new PdfDocumentRenderer(true);
renderer.Document = this.document;
renderer.RenderDocument();
renderer.PrepareRenderPages();
CreateWatermarks(renderer);
byte[] pdfContents = null;
using (MemoryStream stream = new MemoryStream())
{
renderer.PdfDocument.Save(stream, true);
pdfContents = stream.ToArray();
}
return pdfContents;
}
private void CreateWatermarks(PdfDocumentRenderer renderer)
{
int pages = renderer.DocumentRenderer.FormattedDocument.PageCount;
for (int i = 0; i < pages; ++i)
{
var page = renderer.PdfDocument.Pages[i];
XFont font = new XFont("Verdana", 27, XFontStyle.Bold);
XGraphics gfx = XGraphics.FromPdfPage(page, XGraphicsPdfPageOptions.Prepend);
XSize size = gfx.MeasureString("Watermark", font);
gfx.TranslateTransform(pageActiveWidth / 2, pageActiveHeight / 2);
gfx.RotateTransform(-Math.Atan(pageActiveHeight / pageActiveWidth) * 180 / Math.PI);
gfx.TranslateTransform(-pageActiveWidth / 2, -pageActiveHeight / 2);
XStringFormat format = new XStringFormat();
format.Alignment = XStringAlignment.Near;
format.LineAlignment = XLineAlignment.Near;
XBrush brush = new XSolidBrush(XColor.FromArgb(128, 255, 0, 0));
gfx.DrawString("Watermark", font, brush, new XPoint((pageActiveWidth - size.Width) / 2, (pageActiveHeight - size.Height) / 2), format);
}
}

React native : Json.stringify cannot serialize cyclic structure

The issue happened here while using canvas property.
I tried to create roulette in react native using canvas property. I successfully used canvas, except I cannot use ctx.drawImage methods. When I tried to use them I got an error like
JSON.Stringify cannot serialize cyclic structures
Here is a code snipet
componentDidMount(){
wheelCanvas = this.updateCanvas();
}
// This is in error while rendering :
ctx.drawImage(wheelCanvas, wheelCanvas.width / 2, wheelCanvas.height / 2);
updateCanvas() {
var outsideRadius = 120;
var textRadius = 100;
var insideRadius = 30;
var canvas = this.refs.canvasRoulette;
let ctx = canvas.getContext("2d");
canvas.width = canvas.height = outsideRadius * 2 + 6;
var x = outsideRadius + 3;
var y = outsideRadius + 3;
ctx.font = "bold 18px Helvetica, Arial";
for (var i = 0; i < rouletteSize; i++) {
var angle = i * arc;
ctx.fillStyle = colors[i];
ctx.beginPath();
ctx.arc(x, y, outsideRadius, angle, angle + arc, false);
ctx.arc(x, y, insideRadius, angle + arc, angle, true);
ctx.strokeStyle = "#fff";
ctx.lineWidth = 1;
ctx.stroke();
ctx.fill();
ctx.save();
ctx.shadowOffsetX = -1;
ctx.shadowOffsetY = -1;
ctx.shadowBlur = 0;
ctx.shadowColor = "rgb(220,220,220)";
ctx.fillStyle = "#fff";
ctx.translate(
x + Math.cos(angle + arc / 2) * textRadius,
y + Math.sin(angle + arc / 2) * textRadius
);
ctx.rotate(angle + arc / 2 + Math.PI);
var text = numbers[i];
ctx.fillText(text, -ctx.measureText(text).width / 2, 5);
ctx.restore();
}
return canvas;
}

iText 7 - Add and Remove Watermark on a PDF

I would like to add and remove a watermark to a PDF using iText 7. I was able to add the watermark, but unable to remove it again. I could only find relevant code/examples related to iText 5. Any pointers appreciated, thanks.
This is how I added the Watermark (using Layers):
pdfDoc = new PdfDocument(new PdfReader(sourceFile), new PdfWriter(destinationPath));
var numberOfPages = pdfDoc.GetNumberOfPages();
PageSize ps = pdfDoc.GetDefaultPageSize();
for (var i = 1; i <= numberOfPages; i++)
{
PdfPage page = pdfDoc.GetPage(i);
PdfLayer layer = new PdfLayer("watermark", pdfDoc);
var canvas = new PdfCanvas(page);
var pageSize = page.GetPageSize();
var paragraph = new Paragraph(message.WatermarkText).SetFontSize(60);
paragraph.SetFontColor(Color.BLACK, 0.2f);
Canvas canvasModel;
canvas.BeginLayer(layer);
canvasModel = new Canvas(canvas, pdfDoc, ps);
canvasModel.ShowTextAligned(paragraph, pageSize.GetWidth() / 2, pageSize.GetHeight() / 2, pdfDoc.GetPageNumber(page), TextAlignment.CENTER, VerticalAlignment.MIDDLE, 45);
canvasModel.SetFontColor(Color.GREEN, 0.2f);
canvas.EndLayer();
}
pdfDoc.Close();
This is what I have tried to remove the watermark. I want to remove it completely, not just set the layer to not display.(any sample code appreciated):
pdfDoc = new PdfDocument(new PdfReader(sourceFile), new PdfWriter(destinationPath));
IList<PdfLayer> layers = pdfDoc.GetCatalog().GetOCProperties(true).GetLayers();
for (var i = 0; i <= layers.Count; i++)
{
var t = layers[i].GetPdfObject().Get(PdfName.Name);
if (t.ToString().Equals("watermark"))
{
//Not what I want..need to remove the layer
layers[i].SetOn(false);
//This does not work...
//layers.RemoveAt(i);
}
}
pdfDoc.Close();
With help from the guys at iText I was able to solve this.
If you intend to remove the watermark later, you will need to add it as a 'PDF watermark annotation'.
To add a watermark on every page:
public void WatermarkPDF(string sourceFile, string destinationPath)
{
float watermarkTrimmingRectangleWidth = 300;
float watermarkTrimmingRectangleHeight = 300;
float formWidth = 300;
float formHeight = 300;
float formXOffset = 0;
float formYOffset = 0;
float xTranslation = 50;
float yTranslation = 25;
double rotationInRads = Math.PI / 3;
PdfFont font = PdfFontFactory.CreateFont(FontConstants.TIMES_ROMAN);
float fontSize = 50;
PdfDocument pdfDoc = new PdfDocument(new PdfReader(sourceFile), new PdfWriter(destinationPath));
var numberOfPages = pdfDoc.GetNumberOfPages();
PdfPage page = null;
for (var i = 1; i <= numberOfPages; i++)
{
page = pdfDoc.GetPage(i);
Rectangle ps = page.GetPageSize();
//Center the annotation
float bottomLeftX = ps.GetWidth() / 2 - watermarkTrimmingRectangleWidth / 2;
float bottomLeftY = ps.GetHeight() / 2 - watermarkTrimmingRectangleHeight / 2;
Rectangle watermarkTrimmingRectangle = new Rectangle(bottomLeftX, bottomLeftY, watermarkTrimmingRectangleWidth, watermarkTrimmingRectangleHeight);
PdfWatermarkAnnotation watermark = new PdfWatermarkAnnotation(watermarkTrimmingRectangle);
//Apply linear algebra rotation math
//Create identity matrix
AffineTransform transform = new AffineTransform();//No-args constructor creates the identity transform
//Apply translation
transform.Translate(xTranslation, yTranslation);
//Apply rotation
transform.Rotate(rotationInRads);
PdfFixedPrint fixedPrint = new PdfFixedPrint();
watermark.SetFixedPrint(fixedPrint);
//Create appearance
Rectangle formRectangle = new Rectangle(formXOffset, formYOffset, formWidth, formHeight);
//Observation: font XObject will be resized to fit inside the watermark rectangle
PdfFormXObject form = new PdfFormXObject(formRectangle);
PdfExtGState gs1 = new PdfExtGState().SetFillOpacity(0.6f);
PdfCanvas canvas = new PdfCanvas(form, pdfDoc);
float[] transformValues = new float[6];
transform.GetMatrix(transformValues);
canvas.SaveState()
.BeginText().SetColor(Color.GRAY, true).SetExtGState(gs1)
.SetTextMatrix(transformValues[0], transformValues[1], transformValues[2], transformValues[3], transformValues[4], transformValues[5])
.SetFontAndSize(font, fontSize)
.ShowText("watermark text")
.EndText()
.RestoreState();
canvas.Release();
watermark.SetAppearance(PdfName.N, new PdfAnnotationAppearance(form.GetPdfObject()));
watermark.SetFlags(PdfAnnotation.PRINT);
page.AddAnnotation(watermark);
}
page?.Flush();
pdfDoc.Close();
}
To remove the watermark:
public void RemovetWatermarkPDF(string sourceFile, string destinationPath)
{
PdfDocument pdfDoc = new PdfDocument(new PdfReader(sourceFile), new PdfWriter(destinationPath));
var numberOfPages = pdfDoc.GetNumberOfPages();
for (var i = 1; i <= numberOfPages; i++)
{
// PdfAnnotation
PdfDictionary pageDict = pdfDoc.GetPage(i).GetPdfObject();
PdfArray annots = pageDict.GetAsArray(PdfName.Annots);
for (int j = 0; j < annots.Size(); j++)
{
PdfDictionary annotation = annots.GetAsDictionary(j);
if (PdfName.Watermark.Equals(annotation.GetAsName(PdfName.Subtype)))
{
annotation.Clear();
}
}
}
pdfDoc.Close();
}
What about variable length watermark text? How would you dynamically resize the rectangle to fit the text? This is not inbuilt into iText, you would need to play around with the following dimension parameters:
float watermarkTrimmingRectangleWidth = 600;
float watermarkTrimmingRectangleHeight = 600;
float formWidth = 600;
float formHeight = 600;
float formXOffset = -100;
float fontSize = 30;
For my use-case I checked the length of the watermark text and based on that adjusted the parameters accordingly eg:
if (watermarkText.Length <= 14)
{
watermarkTrimmingRectangleWidth = 200;
watermarkTrimmingRectangleHeight = 200;
formWidth = 200;
formHeight = 200;
formXOffset = 0;
fontSize = 30;
}
else if (watermarkText.Length <= 22)
{
watermarkTrimmingRectangleWidth = 300;
watermarkTrimmingRectangleHeight = 300;
formWidth = 300;
formHeight = 300;
formXOffset = 0;
fontSize = 30;
}
else if (...)
{
...
}
.
.
etc.
.
.
else if (watermarkText.Length <= 62)
{
watermarkTrimmingRectangleWidth = 600;
watermarkTrimmingRectangleHeight = 600;
formWidth = 600;
formHeight = 600;
formXOffset = -100;
fontSize = 20;
}

how to crop image from the center automatically after uploaded image in c#?

I want to crop the image from the center upload time in c#. I have try bellow this code but don't return new image.
[AllowAnonymous]
[HttpPost]
public string Upload(string dataImage, string Pusername, double dataX = 0, double? dataY = 0, double? dataHeight = 0, double? dataWidth = 0, double? dataRotate = 0)
{
if (!String.IsNullOrEmpty(dataImage))
{
try
{
string lenght = dataImage.Substring(0, dataImage.LastIndexOf(","));
string test = dataImage.Remove(0, lenght.Length + 1);
byte[] imageBytes = Convert.FromBase64String(test);
MemoryStream ms = new MemoryStream(imageBytes, 0, imageBytes.Length);
ms.Write(imageBytes, 0, imageBytes.Length);
Bitmap image1 = new Bitmap(ms);
Rectangle rect = new Rectangle(Convert.ToInt32(dataX), Convert.ToInt32(dataY), Convert.ToInt32(dataWidth), Convert.ToInt32(dataHeight));
Bitmap cropped = null;
if (dataX != 0 || dataY != 0 || dataHeight != 0 || dataWidth != 0)
{
cropped = RotateImageByAngle(image1, rect, (float)dataRotate);
}
else
{
cropped = (Bitmap)ResizeImage(image1, new Size(image1.Width, image1.Height));
}
string fileName = string.Empty;
string Destintionpath = string.Empty;
string FileExtensionType = System.Drawing.Imaging.ImageCodecInfo.GetImageEncoders().FirstOrDefault(x => x.FormatID == image1.RawFormat.Guid).FilenameExtension;
string FinalFileExtension;
if (FileExtensionType.ToLower().Contains("jpg") || FileExtensionType.ToLower().Contains("jpeg") || FileExtensionType.ToLower().Contains("jfif"))
FinalFileExtension = "jpeg";
else if (FileExtensionType.ToLower().Contains("png"))
FinalFileExtension = "png";
else if (FileExtensionType.ToLower().Contains("bmp"))
FinalFileExtension = "bmp";
else
FinalFileExtension = "gif";
fileName = System.IO.Path.GetFileName(Pusername+ "_" + DateTime.UtcNow.ToString("mmddyyyy-Hmmss", CultureInfo.InvariantCulture) + "." + FinalFileExtension);
Destintionpath = System.IO.Path.Combine(Server.MapPath("~/" + ConfigurationManager.AppSettings["ImagesFolder"].ToString() + "/"), fileName);
string databasepath = Request.Url.GetLeftPart(UriPartial.Authority) + "/" + ConfigurationManager.AppSettings["ImagesFolder"].ToString() + "/" + fileName;
string FileExtension = fileName.Substring(fileName.LastIndexOf('.') + 1, fileName.Length - (fileName.LastIndexOf('.') + 1));
if (FileExtension.ToLower() == "jpg" || FileExtension.ToLower() == "jpeg")
ImageCompressionJpeg.Compress(cropped, Destintionpath);
else if (FileExtension.ToLower() == "png")
ImageCompressionJpeg.RemoveTransparency(cropped, Destintionpath);
else
cropped.Save(Destintionpath);
RegisterModel objregister = new RegisterModel();
objregister.UserName = Profile.UserName;
objregister.CloudImagePath = databasepath;
string result = u.UserThumbnail(objregister).Result;
return databasepath;
}
catch
{
return "error";
}
}
else
{
return "error";
}
}
Here is below my ResizeImage method this method are used for the image crop but I don't return new croping image.
public static Image ResizeImage(Image imgToResize, Size destinationSize)
{
var originalWidth = imgToResize.Width;
var originalHeight = imgToResize.Height;
var hRatio = (float)originalHeight / destinationSize.Height;
var wRatio = (float)originalWidth / destinationSize.Width;
var ratio = Math.Min(hRatio, wRatio);
var hScale = Convert.ToInt32(destinationSize.Height * ratio);
var wScale = Convert.ToInt32(destinationSize.Width * ratio);
var startX = (originalWidth - wScale) / 2;
var startY = (originalHeight - hScale) / 2;
var sourceRectangle = new Rectangle(startX, startY, wScale, hScale);
var bitmap = new Bitmap(destinationSize.Width, destinationSize.Height);
var destinationRectangle = new Rectangle(0, 0, bitmap.Width, bitmap.Height);
using (var g = Graphics.FromImage(bitmap))
{
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.DrawImage(imgToResize, destinationRectangle, sourceRectangle, GraphicsUnit.Pixel);
}
return bitmap;
}
You can use,
using (var g = Graphics.FromImage(bitmap))
{
g.TranslateTransform((float)bitmap.Width / 2, (float)bitmap.Height / 2);
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.DrawImage(imgToResize, destinationRectangle, sourceRectangle, GraphicsUnit.Pixel);
}
Hope this helps!

Mobius strip has a seam! Java3D

I'm creating a mobius strip in Java3D. I've got a seam and I can't seem to get rid of it! I'm assuming it's got to do with normals and the fact that the difference in angle between the conjoined edges is technically 180. Can anyone help me remove this seam?
Here's my code:
public class MobiusStrip extends Applet {
public static void main(String[] args){
new MainFrame(new MobiusStrip(), 800, 600);
}
#Override
public void init(){
GraphicsConfiguration gc = SimpleUniverse.getPreferredConfiguration();
Canvas3D canvas = new Canvas3D(gc);
this.setLayout(new BorderLayout());
this.add(canvas, BorderLayout.CENTER);
SimpleUniverse su = new SimpleUniverse(canvas);
su.getViewingPlatform().setNominalViewingTransform();
BranchGroup bg = createSceneGraph();
bg.compile();
su.addBranchGraph(bg);
}
private BranchGroup createSceneGraph(){
BranchGroup root = new BranchGroup();
Shape3D shape = new Shape3D();
shape.setGeometry(mobius().getIndexedGeometryArray());
//Scaling transform
Transform3D tr = new Transform3D();
tr.setScale(0.5);
//Spin transform group
TransformGroup spin = new TransformGroup();
spin.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
root.addChild(spin);
//Set appearance
Appearance ap = new Appearance();
PointAttributes pa = new PointAttributes(10, true);
ap.setPointAttributes(pa);
ap.setPolygonAttributes(new PolygonAttributes
(PolygonAttributes.POLYGON_FILL,
PolygonAttributes.CULL_NONE, 0));
//Set materials
Material mat = new Material();
mat.setLightingEnable(true);
mat.setShininess(30);
ap.setMaterial(mat);
//Overarching Transform group
TransformGroup tg = new TransformGroup(tr);
tg.addChild(shape);
spin.addChild(tg);
shape.setAppearance(ap);
//Set rotation
Alpha alpha = new Alpha(-1, 6000);
RotationInterpolator rotate = new RotationInterpolator(alpha, spin);
BoundingSphere bounds = new BoundingSphere();
rotate.setSchedulingBounds(bounds);
spin.addChild(rotate);
//Set background
Background background = new Background(1.0f, 1.0f, 1.0f);
background.setApplicationBounds(bounds);
root.addChild(background);
//Set lighting
AmbientLight light = new AmbientLight(true, new Color3f(Color.BLACK));
light.setInfluencingBounds(bounds);
root.addChild(light);
PointLight ptlight = new PointLight(new Color3f(Color.white),
new Point3f(0.5f,0.5f,1f),
new Point3f(1f,0.2f,0f));
ptlight.setInfluencingBounds(bounds);
root.addChild(ptlight);
return root;
}//Close branchgroup method
//Create the Mobius shape
private GeometryInfo mobius()
{
int m = 100; //number of row points
int n = 100; //number of col points
int p = 4*((m-1)*(n-1)); //faces * points per face
IndexedQuadArray iqa = new IndexedQuadArray(m*n,
GeometryArray.COORDINATES, p);
Point3d[] vertices = new Point3d[m*n];
int index = 0;
//Create vertices
for(int i = 0; i < m; i++)
{
for(int j = 0; j < n; j++)
{
double u = i * (2*(Math.PI))/(m - 1);
double v = -0.3 + (j * (0.6/(n-1)));
double x=(1+v*Math.cos(u/2))*Math.cos(u);
double y=(1+v*Math.cos(u/2))*Math.sin(u);
double z=v*Math.sin(u/2);
vertices[index]=new Point3d(x,y,z);
index++;
}//close nested for loop
}//close for loop
iqa.setCoordinates(0, vertices);
index = 0;
//set index for coordinates
for(int i = 0; i < m-1; i++){
for(int j = 0; j < n-1; j++){
iqa.setCoordinateIndex(index, i*m+j);
index++;
iqa.setCoordinateIndex(index, i*m+j+1);
index++;
iqa.setCoordinateIndex(index, (i+1)*m+j+1);
index++;
iqa.setCoordinateIndex(index, (i+1)*m+j);
index++;
}//close nested for loop
}//close for loop
//create geometry info and generate normals for shape
GeometryInfo gi = new GeometryInfo(iqa);
NormalGenerator ng = new NormalGenerator();
ng.generateNormals(gi);
return gi;
}
}
See this question for more explanation. You'll need two changes:
ap.setPolygonAttributes(new PolygonAttributes(PolygonAttributes.POLYGON_FILL, PolygonAttributes.CULL_BACK, 0));
double u = i * (4 * (Math.PI)) / (m - 1);