npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

remove-gemini-watermark

v0.1.2

Published

Remove Gemini / Nano Banana watermarks from images. Pure local processing, no upload. Works in browser and Node.js.

Downloads

319

Readme

remove-gemini-watermark

Remove Gemini / Nano Banana watermarks from images — locally, with no uploads.

Works in Node.js (CLI / server) and browser (Vite / webpack / any bundler).

| Entry | Environment | Exports | |-------|-------------|--------| | remove-gemini-watermark | Node.js | processFile + removeWatermark | | remove-gemini-watermark/browser | Browser | removeWatermark + readImageBuffer + pixelsToBlob |

How It Works

Uses Reverse Alpha Blending to mathematically recover the original pixels hidden beneath the semi-transparent watermark overlay:

original = (blended - watermark × α) / (1 - α)

The watermark shape and opacity are encoded in bundled mask templates. No AI models, no network requests — pure pixel math.

CLI Usage

npx (no install required)

npx remove-gemini-watermark photo.png

Global install

npm install -g remove-gemini-watermark
remove-gemini-watermark photo.png

Examples

# Single file — modified in-place
remove-gemini-watermark photo.png

# Multiple files
remove-gemini-watermark a.png b.jpg c.webp

# Entire directory (recursive)
remove-gemini-watermark ./photos

# Mix of files and directories
remove-gemini-watermark ./screenshots export.png

Supported formats: PNG · JPG / JPEG · WebP

Files are modified in-place. Back up originals if needed.

Programmatic API

Node.js — processFile()

import { processFile } from 'remove-gemini-watermark';

const result = await processFile('photo.png');
console.log(result.detected);               // true if watermark was found
console.log(result.debug.processedPixels);  // number of pixels modified

// Custom output path (original is preserved)
await processFile('photo.png', { output: 'photo_clean.png' });

// Adjust alpha strength (default: 1)
await processFile('photo.png', { alphaStrength: 1.2 });

Browser — remove-gemini-watermark/browser

Browser-only entry. Zero dependencies — sharp is never bundled.

With <input type="file">

import { removeWatermark, readImageBuffer, pixelsToBlob } from 'remove-gemini-watermark/browser';

async function handleFile(file: File) {
  // 1. Decode file → PixelData
  const pixels = await readImageBuffer(file);

  // 2. Remove watermark (in-place)
  const result = await removeWatermark(pixels);
  console.log(result.detected, result.debug);

  // 3. Encode back to Blob → Object URL
  const blob = await pixelsToBlob(pixels, 'image/png');
  const url = URL.createObjectURL(blob);

  const img = document.createElement('img');
  img.src = url;
  document.body.appendChild(img);
}

document.querySelector('input[type=file]')
  .addEventListener('change', e => handleFile(e.target.files[0]));

With Canvas ImageData

import { removeWatermark } from 'remove-gemini-watermark/browser';

const canvas = document.getElementById('myCanvas') as HTMLCanvasElement;
const ctx = canvas.getContext('2d')!;
const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);

const pixels = {
  data: imageData.data,
  width: canvas.width,
  height: canvas.height,
};

const result = await removeWatermark(pixels);
// pixels.data is modified in-place
ctx.putImageData(imageData, 0, 0);

React / Vite example

import { removeWatermark, readImageBuffer, pixelsToBlob } from 'remove-gemini-watermark/browser';

export function WatermarkRemover() {
  const [resultUrl, setResultUrl] = useState<string>();

  async function handleDrop(file: File) {
    const pixels = await readImageBuffer(file);
    const result = await removeWatermark(pixels);
    if (result.detected) {
      const blob = await pixelsToBlob(pixels);
      setResultUrl(URL.createObjectURL(blob));
    }
  }

  return (
    <div onDrop={e => handleDrop(e.dataTransfer.files[0])}>
      {resultUrl && <img src={resultUrl} />}
    </div>
  );
}

API Reference

removeWatermark(pixels, options?) — universal

Modifies pixels.data in-place and returns a result.

| Option | Type | Default | Description | |--------|------|---------|-------------| | alphaStrength | number | 1 | Multiply mask alpha — increase if watermark is not fully removed | | force | boolean | false | Process even when watermark is not detected |

processFile(inputPath, options?) — Node.js only

| Option | Type | Default | Description | |--------|------|---------|-------------| | output | string | same as input | Output file path | | alphaStrength | number | 1 | See above | | force | boolean | false | See above |

RemoveResult

{
  detected: boolean;
  debug: {
    maskSize: number;        // 48 or 96 (px)
    watermarkBrightness: number;
    surroundBrightness: number;
    brightnessDiff: number;  // > 10 means watermark detected
    processedPixels: number;
  };
}

Requirements

  • CLI / Node.js: Node.js >= 18, sharp (installed automatically as an optional dependency)
  • Browser: any modern browser supporting createImageBitmap and OffscreenCanvas (Chrome 69+, Firefox 105+, Safari 16.4+)

Development

Setup

git clone https://github.com/YOUR_USERNAME/remove-gemini-watermark.git
cd remove-gemini-watermark
pnpm install

Build

pnpm build

Output goes to dist/. The CLI entry is dist/cli.js.

Watch mode

pnpm dev

Rebuilds automatically on source changes.

Local testing

Link the package globally so the remove-gemini-watermark command is available system-wide:

npm link

Then test with any image:

remove-gemini-watermark ~/Downloads/photo.png

After making changes, just rebuild — no need to re-link:

pnpm build
# the command is updated immediately

To unlink when done:

npm unlink -g remove-gemini-watermark

Project structure

src/
├── algorithm.ts        # Pure algorithm — mask data, detection, reverse blending (zero deps)
├── io.ts               # I/O — runtime branch: Canvas API (browser) / sharp (Node.js)
├── remove-watermark.ts # Orchestrator — combines algorithm + io, exports shared API
├── browser.ts          # Browser entry — removeWatermark + readImageBuffer + pixelsToBlob
├── cli.ts              # CLI entry — argument parsing, file/directory walking
└── index.ts            # Node.js public API exports

Publishing

npm version patch   # or minor / major
npm publish

prepublishOnly runs build automatically before publishing.

License

MIT