Skip to content

Instantly share code, notes, and snippets.

@bczhc
Last active November 29, 2025 10:42
Show Gist options
  • Select an option

  • Save bczhc/72ffd278d3a2d86a62c25794829df20e to your computer and use it in GitHub Desktop.

Select an option

Save bczhc/72ffd278d3a2d86a62c25794829df20e to your computer and use it in GitHub Desktop.
通过识别`ADBE_CompoundType`标记去除PDF水印。 #pdf #adobe
#![feature(try_blocks)]
use clap::Parser;
use lopdf::{Document, Object, ObjectId};
use std::path::PathBuf;
#[derive(clap::Parser)]
struct Args {
input: PathBuf,
output: PathBuf,
}
fn main() -> anyhow::Result<()> {
let args = Args::parse();
eprintln!("Loading...");
let mut doc = Document::load(&args.input)?;
eprintln!("Decompressing...");
eprintln!("Object count: {}", doc.objects.len());
let watermark = watermark_objects(&doc);
eprintln!("Watermark objects: {:?}", watermark);
eprintln!("Removing...");
for id in watermark.iter() {
doc.delete_object(*id);
}
if !watermark.is_empty() {
let output = &args.output;
eprintln!("Save to: {}", output.display());
doc.save(output)?;
}
Ok(())
}
fn watermark_objects(doc: &Document) -> Vec<ObjectId> {
fn check(obj: &Object) -> bool {
let r: anyhow::Result<_> = try {
obj.as_stream()?
.dict
.get(b"PieceInfo")?
.as_dict()?
.get(b"ADBE_CompoundType")?
.as_dict()?
.get(b"Private")?
.as_name()?
== b"Watermark"
};
r.unwrap_or(false)
}
let mut vec = Vec::new();
for obj in &doc.objects {
if check(&obj.1) {
vec.push(*obj.0);
}
}
vec
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment