chore(userscript): improve performance
parent
18d9e6b5e6
commit
8d95184abe
2
build.js
2
build.js
|
|
@ -5,7 +5,7 @@ const userscriptBanner = `// ==UserScript==
|
||||||
// @name Gemini NanoBanana Watermark Remover
|
// @name Gemini NanoBanana Watermark Remover
|
||||||
// @name:zh-CN Gemini NanoBanana 图片水印移除
|
// @name:zh-CN Gemini NanoBanana 图片水印移除
|
||||||
// @namespace https://github.com/journey-ad
|
// @namespace https://github.com/journey-ad
|
||||||
// @version 0.1.3
|
// @version 0.1.4
|
||||||
// @description Automatically removes watermarks from Gemini AI generated images
|
// @description Automatically removes watermarks from Gemini AI generated images
|
||||||
// @description:zh-CN 自动移除 Gemini AI 生成图像中的水印
|
// @description:zh-CN 自动移除 Gemini AI 生成图像中的水印
|
||||||
// @icon https://www.google.com/s2/favicons?domain=gemini.google.com
|
// @icon https://www.google.com/s2/favicons?domain=gemini.google.com
|
||||||
|
|
|
||||||
|
|
@ -21,8 +21,7 @@ const loadImage = (src) => new Promise((resolve, reject) => {
|
||||||
const canvasToBlob = (canvas, type = 'image/png') =>
|
const canvasToBlob = (canvas, type = 'image/png') =>
|
||||||
new Promise(resolve => canvas.toBlob(resolve, type));
|
new Promise(resolve => canvas.toBlob(resolve, type));
|
||||||
|
|
||||||
const isValidGeminiImage = (img) =>
|
const isValidGeminiImage = (img) => img.closest('model-response,.generated-image-container') !== null;
|
||||||
/=s\d+\-rj/.test(img.src) || (img.naturalWidth >= 256 && img.naturalHeight >= 256);
|
|
||||||
|
|
||||||
const findGeminiImages = () =>
|
const findGeminiImages = () =>
|
||||||
[...document.querySelectorAll('img[src*="googleusercontent.com"]')].filter(isValidGeminiImage);
|
[...document.querySelectorAll('img[src*="googleusercontent.com"]')].filter(isValidGeminiImage);
|
||||||
|
|
@ -49,23 +48,17 @@ async function processImage(imgElement) {
|
||||||
processingQueue.add(imgElement);
|
processingQueue.add(imgElement);
|
||||||
imgElement.dataset.watermarkProcessed = 'processing';
|
imgElement.dataset.watermarkProcessed = 'processing';
|
||||||
|
|
||||||
try {
|
|
||||||
if (!isValidGeminiImage(imgElement)) {
|
|
||||||
imgElement.dataset.watermarkProcessed = 'skipped';
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const originalSrc = imgElement.src;
|
const originalSrc = imgElement.src;
|
||||||
|
try {
|
||||||
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));
|
URL.revokeObjectURL(normalSizeBlobUrl);
|
||||||
const blobUrl = URL.createObjectURL(blob);
|
|
||||||
const img = await loadImage(blobUrl);
|
|
||||||
const canvas = await engine.removeWatermarkFromImage(img);
|
|
||||||
const processedBlob = await canvasToBlob(canvas);
|
|
||||||
|
|
||||||
URL.revokeObjectURL(blobUrl);
|
|
||||||
imgElement.src = URL.createObjectURL(processedBlob);
|
imgElement.src = URL.createObjectURL(processedBlob);
|
||||||
imgElement.dataset.watermarkProcessed = 'true';
|
imgElement.dataset.watermarkProcessed = 'true';
|
||||||
|
|
||||||
|
|
@ -73,6 +66,7 @@ async function processImage(imgElement) {
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.warn('[Gemini Watermark Remover] Failed to process image:', error);
|
console.warn('[Gemini Watermark Remover] Failed to process image:', error);
|
||||||
imgElement.dataset.watermarkProcessed = 'failed';
|
imgElement.dataset.watermarkProcessed = 'failed';
|
||||||
|
imgElement.src = originalSrc;
|
||||||
} finally {
|
} finally {
|
||||||
processingQueue.delete(imgElement);
|
processingQueue.delete(imgElement);
|
||||||
}
|
}
|
||||||
|
|
@ -80,6 +74,8 @@ async function processImage(imgElement) {
|
||||||
|
|
||||||
const processAllImages = () => {
|
const processAllImages = () => {
|
||||||
const images = findGeminiImages();
|
const images = findGeminiImages();
|
||||||
|
if (images.length === 0) return;
|
||||||
|
|
||||||
console.log(`[Gemini Watermark Remover] Found ${images.length} images to process`);
|
console.log(`[Gemini Watermark Remover] Found ${images.length} images to process`);
|
||||||
images.forEach(processImage);
|
images.forEach(processImage);
|
||||||
};
|
};
|
||||||
|
|
@ -98,7 +94,8 @@ async function processImageBlob(blob) {
|
||||||
return canvasToBlob(canvas);
|
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
|
// Intercept fetch requests to replace downloadable image with the watermark removed image
|
||||||
const { fetch: origFetch } = unsafeWindow;
|
const { fetch: origFetch } = unsafeWindow;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue