How to create a stamp that is ignored by text to speech

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();
		}
	}
}
1 Like