chore(userscript): improve performance

main
Jad 2025-12-20 20:43:39 +08:00
parent 18d9e6b5e6
commit 8d95184abe
2 changed files with 14 additions and 17 deletions

View File

@ -5,7 +5,7 @@ const userscriptBanner = `// ==UserScript==
// @name Gemini NanoBanana Watermark Remover
// @name:zh-CN Gemini NanoBanana 图片水印移除
// @namespace https://github.com/journey-ad
// @version 0.1.3
// @version 0.1.4
// @description Automatically removes watermarks from Gemini AI generated images
// @description:zh-CN 自动移除 Gemini AI 生成图像中的水印
// @icon https://www.google.com/s2/favicons?domain=gemini.google.com

View File

@ -21,8 +21,7 @@ const loadImage = (src) => new Promise((resolve, reject) => {
const canvasToBlob = (canvas, type = 'image/png') =>
new Promise(resolve => canvas.toBlob(resolve, type));
const isValidGeminiImage = (img) =>
/=s\d+\-rj/.test(img.src) || (img.naturalWidth >= 256 && img.naturalHeight >= 256);
const isValidGeminiImage = (img) => img.closest('model-response,.generated-image-container') !== null;
const findGeminiImages = () =>
[...document.querySelectorAll('img[src*="googleusercontent.com"]')].filter(isValidGeminiImage);
@ -49,23 +48,17 @@ async function processImage(imgElement) {
processingQueue.add(imgElement);
imgElement.dataset.watermarkProcessed = 'processing';
const originalSrc = imgElement.src;
try {
if (!isValidGeminiImage(imgElement)) {
imgElement.dataset.watermarkProcessed = 'skipped';
return;
}
const originalSrc = imgElement.src;
imgElement.src = '';
imgElement.dataset.src = originalSrc;
const normalSizeBlob = await fetchBlob(replaceWithNormalSize(originalSrc));
const normalSizeBlobUrl = URL.createObjectURL(normalSizeBlob);
const normalSizeImg = await loadImage(normalSizeBlobUrl);
const processedCanvas = await engine.removeWatermarkFromImage(normalSizeImg);
const processedBlob = await canvasToBlob(processedCanvas);
const blob = await fetchBlob(replaceWithNormalSize(originalSrc));
const blobUrl = URL.createObjectURL(blob);
const img = await loadImage(blobUrl);
const canvas = await engine.removeWatermarkFromImage(img);
const processedBlob = await canvasToBlob(canvas);
URL.revokeObjectURL(normalSizeBlobUrl);
URL.revokeObjectURL(blobUrl);
imgElement.src = URL.createObjectURL(processedBlob);
imgElement.dataset.watermarkProcessed = 'true';
@ -73,6 +66,7 @@ async function processImage(imgElement) {
} catch (error) {
console.warn('[Gemini Watermark Remover] Failed to process image:', error);
imgElement.dataset.watermarkProcessed = 'failed';
imgElement.src = originalSrc;
} finally {
processingQueue.delete(imgElement);
}
@ -80,6 +74,8 @@ async function processImage(imgElement) {
const processAllImages = () => {
const images = findGeminiImages();
if (images.length === 0) return;
console.log(`[Gemini Watermark Remover] Found ${images.length} images to process`);
images.forEach(processImage);
};
@ -98,7 +94,8 @@ async function processImageBlob(blob) {
return canvasToBlob(canvas);
}
const GEMINI_URL_PATTERN = /^https:\/\/lh3\.googleusercontent\.com\/rd-gg(-dl)?\//; // downloadable image url pattern
// Only match gemini generated assets(copy & download), ignore user-upload previews.
const GEMINI_URL_PATTERN = /^https:\/\/lh3\.googleusercontent\.com\/rd-gg(?:-dl)?\/.+=s(?!0-d\?).*/;
// Intercept fetch requests to replace downloadable image with the watermark removed image
const { fetch: origFetch } = unsafeWindow;