gpt4 book ai didi

java - 如何使任何 pdf 文件中的水印文本不可选择?

转载 作者:搜寻专家 更新时间:2023-11-01 01:52:49 26 4
gpt4 key购买 nike

我已经使用 itextpdf 在 pdf 文件中完成了水印文本,但是当我复制 pdf 文件的实际文本时,它也允许我们复制水印文本。无论如何,我们可以将我们的水印文本限制为不可选择吗?

Image watermark_image = Image.getInstance(imageFile.getAbsolutePath());

while (i < num_of_pages) {
i++;
//To pass our watermark over text
add_waterMark = pdfStamper.getOverContent(i);

//To pass our watermark under text
//add_waterMark = pdfStamper.getUnderContent(i);

// watermark_image.
watermark_image.setAbsolutePosition(0, 0);

add_waterMark.beginText();
//add_waterMark.setTextRenderingMode(number_of_pages);

//watermark_image is png file
add_waterMark.addImage(watermark_image);

add_waterMark.endText();
}

我已经使用 PdfContentByte 编写了代码,它是空心的和水平的,但我可以在这里复制水印文本:(如果可能的话,我想使用 PdfPatternPainter 替换我的代码,因为 PdfPatternPainter 继承了 PdfContentByte 的所有字段。

这里是使用 PdfContentByte 的代码:

int n = reader.getNumberOfPages();

PdfContentByte under;
PdfGState gstate = new PdfGState();
gstate.setFillOpacity(0.35f);
gstate.setStrokeOpacity(0.35f);
BaseFont font = BaseFont.createFont(BaseFont.HELVETICA_BOLD,
BaseFont.WINANSI, BaseFont.EMBEDDED);

Rectangle size = reader.getPageSizeWithRotation(1);
// float angle = (float) ((180 * (Math.asin(size.getHeight()
// / Math.sqrt(size.getWidth() * size.getWidth()
// + size.getHeight() * size.getHeight())))) / Math.PI);
int i = 1;

while (i < n + 1) {

under = stamper.getOverContent(i);
under.setColorStroke(new BaseColor(192, 192, 192));
i++;
under.beginText();
under.setTextRenderingMode(PdfContentByte.TEXT_RENDER_MODE_STROKE);
under.setLineWidth(0.85f);
under.setLineDash(0.4f, 0.4f, 0.2f);

under.showTextAlignedKerned(Element.ALIGN_MIDDLE,
"user name must required", 250, 780,
MYConstants.WATERMARK_PAGE_ANGLE);
under.setFontAndSize(font, 42);
under.showTextAlignedKerned(Element.ALIGN_MIDDLE,
"user Company name required", 200, 730,
MyConstants.WATERMARK_PAGE_ANGLE);
under.setFontAndSize(font, 42);
under.showTextAlignedKerned(Element.ALIGN_MIDDLE,
"Plesae enter your email id", 150, 680,
MyConstants.WATERMARK_PAGE_ANGLE);


under.endText();
}

stamper.close();
}

最佳答案

在对原始问题的评论中,OP 澄清了

the only things here needed is, whenever you will try to select entire text of pdf, the watermark text should not be selected. i just want to know is there any approach other then using png image file.

这听起来像是使用带有文本内容的模式可能正适合您。这是一个使用 iText 的概念验证:

void addTextPatternToOverContent(File source, File target) throws IOException, DocumentException
{
PdfReader reader = new PdfReader(source.getPath());
OutputStream os = new FileOutputStream(target);
PdfStamper stamper = new PdfStamper(reader, os);

PdfPatternPainter painter = stamper.getOverContent(1).createPattern(200, 150);
painter.setColorFill(BaseColor.BLACK);
painter.beginText();
painter.setTextMatrix(AffineTransform.getTranslateInstance(0, 50));
painter.setFontAndSize(BaseFont.createFont(), 100);
painter.showText("Test");
painter.endText();

for (int i = reader.getNumberOfPages(); i > 0; i--)
{
PdfContentByte overContent = stamper.getOverContent(i);
overContent.setColorFill(new PatternColor(painter));
overContent.rectangle(200, 300, 200, 150);
overContent.fill();
}

stamper.close();
os.close();
reader.close();
}

在 Adob​​e Reader 中无法选择图案中的文本。 @gwillie,这里不需要繁重的工作,这不是安全功能,一旦您知道文本放在哪里就很容易找到。

请注意,模式可能变化无常。对于文本的自由定位,您可能希望用固定形式的 xobject 中的该图案填充一个矩形(因此与图案拼贴在边缘)并将该 xobject 放在您想要的任何位置。

很可能你会想要应用透明度或者不填充而只是像使用这个图案画家一样轻轻地描画字母:

    PdfPatternPainter painter = stamper.getOverContent(1).createPattern(200, 150);
painter.setColorStroke(BaseColor.BLACK);
painter.beginText();
painter.setTextRenderingMode(PdfPatternPainter.TEXT_RENDER_MODE_STROKE);
painter.setTextMatrix(AffineTransform.getTranslateInstance(0, 50));
painter.setFontAndSize(BaseFont.createFont(), 100);
painter.showText("Test");
painter.endText();

PS:考虑到 OP 的新详细代码,将其添加为不可复制和粘贴的内容的方法可能如下所示:

void addUserPatternToOverContent(File source, File target) throws IOException, DocumentException
{
PdfReader reader = new PdfReader(source.getPath());
OutputStream os = new FileOutputStream(target);
PdfStamper stamper = new PdfStamper(reader, os);

Rectangle pageSize = reader.getPageSize(1);
final float WATERMARK_PAGE_ANGLE = -72;

BaseFont font = BaseFont.createFont(BaseFont.HELVETICA_BOLD, BaseFont.WINANSI, BaseFont.NOT_EMBEDDED);

PdfPatternPainter painter = stamper.getOverContent(1).createPattern(pageSize.getWidth(), pageSize.getHeight());
painter.setColorStroke(new BaseColor(192, 192, 192));
painter.setLineWidth(0.85f);
painter.setLineDash(0.4f, 0.4f, 0.2f);

painter.beginText();
painter.setTextRenderingMode(PdfPatternPainter.TEXT_RENDER_MODE_STROKE);
painter.setFontAndSize(font, 42);
painter.showTextAlignedKerned(Element.ALIGN_MIDDLE,
"user name must required", 250, 780,
WATERMARK_PAGE_ANGLE);
painter.showTextAlignedKerned(Element.ALIGN_MIDDLE,
"user Company name required", 200, 730,
WATERMARK_PAGE_ANGLE);
painter.showTextAlignedKerned(Element.ALIGN_MIDDLE,
"Plesae enter your email id", 150, 680,
WATERMARK_PAGE_ANGLE);
painter.endText();

for (int i = reader.getNumberOfPages(); i > 0; i--)
{
Rectangle thisPageSize = reader.getPageSize(i);
PdfContentByte overContent = stamper.getOverContent(i);
overContent.setColorFill(new PatternColor(painter));
overContent.rectangle(thisPageSize.getLeft(), thisPageSize.getBottom(), thisPageSize.getWidth(), thisPageSize.getHeight());
overContent.fill();
}

stamper.close();
os.close();
reader.close();
}

显示例如作为

the water sign applied to a sample page

顺便说一句,我将 Helvetica Bold 更改为未嵌入,因为它是标准的 14 种字体之一。

PPS:在评论中,OP 进一步想知道

is there any way that our watermark text go backgroud of actual text and in case of Image it goes foreground. i have tried with getUnderContent() but our Pdf image Hide this text.

如果不对页面内容进行排序(首先是图像,然后是水印,然后是文本——一般来说并不简单),可以尝试收集所有带有图像的区域(使用 iText 解析器包类),然后放水标记内容不足,内容过多也会放置水印,但仅限于您找到图像的组合区域。更容易实现,但有点脏。例如

void addUserPatternOverAndUnder(File source, File target) throws IOException, DocumentException
{
PdfReader reader = new PdfReader(source.getPath());
OutputStream os = new FileOutputStream(target);
PdfStamper stamper = new PdfStamper(reader, os);

Rectangle pageSize = reader.getPageSize(1);
final float WATERMARK_PAGE_ANGLE = -60;

BaseFont font = BaseFont.createFont(BaseFont.HELVETICA_BOLD, BaseFont.WINANSI, BaseFont.NOT_EMBEDDED);

PdfPatternPainter painter = stamper.getOverContent(1).createPattern(pageSize.getWidth(),
pageSize.getHeight());
painter.setColorStroke(new BaseColor(0, 192, 192));
painter.setLineWidth(0.85f);
painter.setLineDash(0.4f, 0.4f, 0.2f);

painter.beginText();
painter.setTextRenderingMode(PdfPatternPainter.TEXT_RENDER_MODE_STROKE);
painter.setFontAndSize(font, 42);
painter.showTextAlignedKerned(Element.ALIGN_MIDDLE, "user name must required", 150, 780,
WATERMARK_PAGE_ANGLE);
painter.showTextAlignedKerned(Element.ALIGN_MIDDLE, "user Company name required", 100, 730,
WATERMARK_PAGE_ANGLE);
painter.showTextAlignedKerned(Element.ALIGN_MIDDLE, "Plesae enter your email id", 050, 680,
WATERMARK_PAGE_ANGLE);
painter.endText();

for (int i = reader.getNumberOfPages(); i > 0; i--)
{
Rectangle thisPageSize = reader.getPageSize(i);

PdfContentByte underContent = stamper.getUnderContent(i);
underContent.setColorFill(new PatternColor(painter));
underContent.rectangle(thisPageSize.getLeft(), thisPageSize.getBottom(), thisPageSize.getWidth(),
thisPageSize.getHeight());
underContent.fill();

List<Vector> path = getImageBordersPathPoints(reader, i);
if (path != null && !path.isEmpty())
{
PdfContentByte overContent = stamper.getOverContent(i);
overContent.setColorFill(new PatternColor(painter));

for (int index = 0; index < path.size(); index++)
{
Vector corner = path.get(index);
if (index % 4 == 0)
{
overContent.moveTo(corner.get(Vector.I1), corner.get(Vector.I2));
}
else
{
overContent.lineTo(corner.get(Vector.I1), corner.get(Vector.I2));
if (index % 4 == 3)
{
overContent.closePath();
}
}
}
overContent.fill();
}
}

stamper.close();
os.close();
reader.close();
}

static Vector A = new Vector(0, 0, 1);
static Vector B = new Vector(1, 0, 1);
static Vector C = new Vector(1, 1, 1);
static Vector D = new Vector(0, 1, 1);
static List<Vector> positive = Arrays.asList(A, B, C, D);
static List<Vector> negative = Arrays.asList(A, D, C, B);

List<Vector> getImageBordersPathPoints(PdfReader reader, int page) throws IOException
{
final List<Vector> result = new ArrayList<Vector>();
RenderListener listener = new RenderListener()
{
public void renderText(TextRenderInfo renderInfo)
{
}

public void endTextBlock()
{
}

public void beginTextBlock()
{
}

public void renderImage(ImageRenderInfo renderInfo)
{
Matrix ctm = renderInfo.getImageCTM();
List<Vector> unitCorners = ctm.getDeterminant() > 0 ? positive : negative;

for (Vector corner : unitCorners)
{
result.add(corner.cross(ctm));
}
}
};

PdfReaderContentParser parser = new PdfReaderContentParser(reader);
parser.processContent(page, listener);
return result;
}

( vector com.itextpdf.text.pdf.parser.Vector)

结果(Dexx 标志是图片,地址是文本):

the water sign applied to a sample page the new way

不幸的是,解析 API 还没有发出 vector 图形信号。因此, vector 图形(例如,彩色背景,本质上是使用 vector 图形操作绘制的填充矩形)覆盖了水印。

关于java - 如何使任何 pdf 文件中的水印文本不可选择?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20351916/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com