Question: When watermarking using the PDFNET Stamper, using a text to speech feature causes the added text to be detected. How do I ensure that the stamp is consistently ignored by TTS (text-to-speech) software?
Answer: You can add your stamp to a blank PDFDoc Page, vectorize the text, and then use the Stamper to add that page to your desired page. The approach would go like this:
using System;
using pdftron;
using pdftron.Common;
using pdftron.SDF;
using pdftron.PDF;
namespace PDFNetSamples
{
class StamperSample
{
private static pdftron.PDFNetLoader pdfNetLoader = pdftron.PDFNetLoader.Instance();
static StamperSample() {}
static void ProcessElements(ElementReader reader, ElementWriter writer)
{
Element element;
while ((element = reader.Next()) != null)
{
switch (element.GetType())
{
case Element.Type.e_text:
{
Matrix2D ctm = element.GetCTM();
GState gs = element.GetGState();
double fontSize = gs.GetFontSize();
Font font = gs.GetFont();
double hscale = gs.GetHorizontalScale() / 100.0;
Matrix2D textMtx = element.GetTextMatrix();
Matrix2D posMtx = new Matrix2D(1, 0, 0, 1, 0, 0);
Matrix2D fontMtx = new Matrix2D(fontSize * hscale, 0, 0, fontSize, 0, 0);
double unitsPerEm = font.GetUnitsPerEm();
Matrix2D unitsPerEmMtx = new Matrix2D(1.0 / unitsPerEm, 0, 0, -1.0 / unitsPerEm, 0, 0);
fontMtx = fontMtx * unitsPerEmMtx;
for (CharIterator citr = element.GetCharIterator(); citr.HasNext(); citr.Next())
{
CharData charData = citr.Current();
posMtx.m_h = charData.x;
posMtx.m_v = charData.y;
Matrix2D pathMtx = ctm * textMtx * posMtx * fontMtx;
PathData pathData = font.GetGlyphPath(charData.char_code, true);
if (pathData.operators.Length > 0 && pathData.points.Length > 0)
{
double[] points = pathData.points;
for (int i = 0; i < points.Length; i += 2)
{
double x = points[i];
double y = points[i + 1];
pathMtx.Mult(ref x, ref y);
points[i] = x;
points[i + 1] = y;
}
ElementBuilder builder = new ElementBuilder();
Element pathElement = builder.CreatePath(points, points.Length, pathData.operators, pathData.operators.Length);
pathElement.SetPathFill(true);
pathElement.SetPathStroke(false);
pathElement.GetGState().SetFillColorSpace(gs.GetFillColorSpace());
pathElement.GetGState().SetFillColor(gs.GetFillColor());
writer.WritePlacedElement(pathElement);
}
}
break;
}
case Element.Type.e_form:
{
reader.FormBegin();
reader.ClearChangeList();
ProcessElements(reader, writer);
reader.End();
break;
}
default:
break;
}
}
}
static void Main(string[] args)
{
PDFNet.Initialize(PDFTronLicense.Key);
string input_path = "../../../../TestFiles/";
try
{
using (PDFDoc targetDoc = new PDFDoc(input_path + "newsletter.pdf"))
using (PDFDoc tempDoc = new PDFDoc())
using (Stamper s = new Stamper(Stamper.SizeType.e_relative_scale, 1.0, 1.0))
{
tempDoc.PagePushBack(tempDoc.PageCreate());
s.SetAlignment(Stamper.HorizontalAlignment.e_horizontal_center, Stamper.VerticalAlignment.e_vertical_center);
s.SetFontColor(new ColorPt(1, 0, 0)); // set text color to red
s.StampText(tempDoc, "If you are reading this\nthis is an even page", new PageSet(1, tempDoc.GetPageCount()));
ElementWriter writer = new ElementWriter();
ElementReader reader = new ElementReader();
Page vectorTextPage = tempDoc.PageCreate();
Page tempStampedPage = tempDoc.GetPage(1);
reader.Begin(tempStampedPage);
writer.Begin(vectorTextPage, ElementWriter.WriteMode.e_replacement, false, true, tempStampedPage.GetResourceDict());
ProcessElements(reader, writer);
writer.End();
reader.End();
s.StampPage(targetDoc, vectorTextPage, new PageSet(1, targetDoc.GetPageCount()));
targetDoc.Save("stamped_04.pdf", SDFDoc.SaveOptions.e_linearized);
}
}
catch (PDFNetException e)
{
Console.WriteLine(e.Message);
}
PDFNet.Terminate();
}
}
}