feat: add experimental watermark removal by abnormal font and image size · PDFMathTranslate/PDFMathReader@848c530 · GitHub
Skip to content

Commit 848c530

Browse files
committed
feat: add experimental watermark removal by abnormal font and image size
Add an experimental, off-by-default setting (Settings > Experimental) that hides likely watermarks while rendering pages. The PDF file is never modified. Detection runs on the pdf.js operator list and is applied through the page.render operationsFilter, so only the watermark paint operations are skipped: - Text runs are removed when much larger than the body text and also diagonal, translucent, pale, or repeated at the same position across sampled pages. Diagonal translucent text is removed at a lower size threshold. - Images covering 8-85% of the page are removed when translucent, pale or repeated across pages. Full-page images (scans, backgrounds) are kept. - Size alone never removes anything, so titles, running footers and margin stamps stay. - Optional content layers named watermark are hidden. Render caches are keyed by the filter, and toggling the setting re-renders the visible pages. Adds analysis unit tests on real pdf.js operator lists and an Electron canvas pixel smoke test (--smoke-test=watermark).
1 parent 808359a commit 848c530

16 files changed

Lines changed: 743 additions & 5 deletions

‎electron/main/ipc/preferences-ipc.mjs‎

Lines changed: 1 addition & 0 deletions

‎electron/main/services/preferences.mjs‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ const DEFAULT_PREFERENCES = Object.freeze({
6464
automatic: true,
6565
documentLanguageDetection: false,
6666
topicSentenceDetection: false,
67+
watermarkRemovalEnabled: false,
6768
paragraphContinuationDetection: false,
6869
jevApiToken: '',
6970
layoutVisible: false,
@@ -288,6 +289,7 @@ const VALIDATORS = {
288289
automatic: (value) => typeof value === 'boolean',
289290
documentLanguageDetection: (value) => typeof value === 'boolean',
290291
topicSentenceDetection: (value) => typeof value === 'boolean',
292+
watermarkRemovalEnabled: (value) => typeof value === 'boolean',
291293
paragraphContinuationDetection: (value) => typeof value === 'boolean',
292294
jevApiToken: (value) => typeof value === 'string' && value.length <= 4096,
293295
remoteKernelEnabled: (value) => typeof value === 'boolean',
@@ -333,6 +335,7 @@ const VALIDATION_MESSAGES = {
333335
automatic: 'Invalid automatic translation preference',
334336
documentLanguageDetection: 'Invalid document language detection preference',
335337
topicSentenceDetection: 'Invalid topic sentence detection preference',
338+
watermarkRemovalEnabled: 'Invalid watermark removal preference',
336339
paragraphContinuationDetection: 'Invalid paragraph continuation detection preference',
337340
jevApiToken: 'Invalid Jev API token preference',
338341
remoteKernelEnabled: 'Invalid remote kernel preference',

‎src/app/reader-features.mjs‎

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ import { createReaderFit } from '../features/reader/reader-fit.mjs';
66
import { createReaderZoom } from '../features/reader/reader-zoom.mjs';
77
import { createReaderPinch } from '../features/reader/reader-pinch.mjs';
88
import { createCanvasRendering } from '../features/reader/canvas-rendering.mjs';
9+
import { createWatermarkRemoval } from '../features/reader/watermark-removal.mjs';
10+
import { loadPDFRuntime } from '../features/reader/pdf-runtime.mjs';
911
import { createReaderViewport } from '../features/reader/reader-viewport.mjs';
1012
import { createThumbnails } from '../features/reader/reader-thumbnails.mjs';
1113
import { createReaderPreview } from '../features/reader/reader-preview.mjs';
@@ -126,11 +128,22 @@ export function createReaderFeatures({
126128
}),
127129
view,
128130
});
131+
const watermarkRemoval = createWatermarkRemoval({
132+
session,
133+
preferences,
134+
loadRuntime: loadPDFRuntime,
135+
// Frames drawn with the old setting are no longer right.
136+
onToggle: () => {
137+
canvasRendering.resetBitmaps();
138+
void canvasRendering.renderPages(false, true);
139+
},
140+
});
129141
const canvasRendering = createCanvasRendering({
130142
renderState,
131143
session,
132144
motion,
133145
preferences,
146+
watermarkRemoval,
134147
actions: createLazyPort({
135148
rootActions: () => rootActions,
136149
readerViewport: () => readerViewport,

‎src/features/reader/canvas-rendering.mjs‎

Lines changed: 21 additions & 5 deletions

0 commit comments

Comments
 (0)