ClearNano – Nano Banana 浮水印移除工具

ClearNano 是一個輕量、高效且介面現代化的純前端網頁工具,專門用於移除 Gemini 生成圖片中的 Nano 系列浮水印(Banana 浮水印)。本工具完全在瀏覽器端運行,確保您的圖片隱私安全,並使用數學精確的反向 Alpha 混合算法還原影像。

檔案下載:
https://github.com/max32002/ClearNano

使用方式:

  1. 下載專案: 選取所有檔案並下載到本地目錄。
  2. 啟動伺服器: 確保您已安裝 Node.js,然後在專案目錄下執行:
    npx -y http-server -p 8080 -c-1
  3. 開啟應用: 打開瀏覽器訪問 
    http://127.0.0.1:8080
  4. 開始使用
    • 將帶有浮水印的圖片拖入上傳區。
    • 等待處理完成(通常只需幾毫秒)。
    • 點擊圖片查看預覽,或直接點擊「下載」保存還原後的圖片。

YouTube 影片: https://youtu.be/PBL16GJRjTI


antigravity 的提示詞: Model 使用 Claude Opus 4.5 (Thinking)

用 Reverse Alpha Blending 移除 Gemini Nano Banana 浮水印的純前端網頁, 浮水印的mask 圖案在 assets 目錄下, nano banana 生成的浮水印都在圖片最右下角

一次就完成 90% 左右的功能。


✨ ClearNano – Gemini Nano Banana 浮水印移除工具

我已經建立了一個完整的純前端網頁應用程式,用於移除 Gemini Nano Banana 浮水印。

📁 建立的檔案

檔案說明
index.html主要 HTML 結構,包含拖放上傳區、結果展示、預覽模態框
styles.css現代化深色主題樣式,帶有漸層、玻璃態效果、動畫
app.js核心邏輯,包含 Reverse Alpha Blending 算法

🔬 技術原理

使用 Reverse Alpha Blending 公式來還原原始像素:

Pixel_original = (Pixel_final - (α × Pixel_logo)) / (1 - α)
  • Pixel_final: 帶浮水印的像素(我們擁有的)
  • Pixel_logo: 浮水印顏色(白色 = 255)
  • α: 遮罩的 alpha 值
  • Pixel_original: 要還原的原始像素

🎯 功能特色

  1. 純本地處理 – 所有運算都在瀏覽器中完成,圖片不會上傳
  2. 自動偵測遮罩大小 – 根據圖片解析度自動選擇 48×48 或 96×96 遮罩
  3. 拖放上傳 – 支援拖放或點擊選擇多個檔案
  4. 即時預覽 – 可切換查看原圖與處理後的對比
  5. 批次下載 – 支援單張或全部下載

🚀 使用方式

伺服器已在 http://127.0.0.1:8080 運行,您可以直接在瀏覽器中測試!


請 antigravity 幫我們寫 README.md

📝 README.md 更新完成

我已經完整更新了 README.md 文件,內容包含了以下幾個重點:

  1. 詳細的專案介紹:說明這是純前端、保護隱私且數學精確的工具。
  2. 完整的功能列表:列出了純本地處理、反向 Alpha 混合還原、自動偵測解析度、現代化 UI 等特性。
  3. 清晰的使用教學:提供了詳細的本地運行步驟(使用 npx http-server)。
  4. 技術原理解析:解釋了 Reverse Alpha Blending 的數學公式。
  5. 免責聲明與注意事項:特別提醒使用者關閉指紋防禦插件。

您現在可以在 GitHub 或本地查看更新後的說明文件。應用程式伺服器仍在運行中,您可以繼續測試或使用。


我執行時遇到錯誤訊息, 直接貼到 antigravity

C:\Max\git\ClearNano>npx -y http-server -p 8080 -c-1
node:events:486
      throw er; // Unhandled 'error' event
      ^

Error: listen EADDRINUSE: address already in use 0.0.0.0:8080
    at Server.setupListenHandle [as _listen2] (node:net:1940:16)
    at listenInCluster (node:net:1997:12)
    at node:net:2206:7
    at process.processTicksAndRejections (node:internal/process/task_queues:90:21)
Emitted 'error' event on Server instance at:
    at emitErrorNT (node:net:1976:8)
    at process.processTicksAndRejections (node:internal/process/task_queues:90:21) {
  code: 'EADDRINUSE',
  errno: -4091,
  syscall: 'listen',
  address: '0.0.0.0',
  port: 8080
}

Node.js v24.11.0

回答:


提示詞: (附註: 這裡 Model 使用 gemini 3 pro High)

為什麼在網頁看沒有浮水印, 下載的 _clean.png 還是有浮水印?

這很有可能是因為瀏覽器預覽時圖片被縮放了,導致肉眼看不出還原的瑕疵,但下載後的原圖(100% 檢視)這些瑕疵就顯現出來了。

這通常是因為 Reverse Alpha Blending 算法在處理 JPEG 壓縮失真(JPEG Artifacts)的圖片時,無法完美還原,會留下邊緣痕跡。當您在網頁上看到縮小的預覽圖時,這些微小的像素噪點被平滑掉了;但當您下載並放大查看時,它們就變得明顯。

為了讓您能準確檢查結果,我會優化 app.js 和 styles.css,做以下改進:

  1. 修正 Canvas 尺寸讀取:使用 naturalWidth 確保讀取到真實的圖片解析度。
  2. 增強預覽功能:在預覽視窗加入 1:1 原尺寸檢視 功能,讓您在下載前就能看清真實的處理結果。

我現在馬上為您修改程式碼。


提示詞: (附註: 這裡 Model 使用 gemini 3 pro High)

預覽時, 圖片太太無法 scroll, 超過的地方被覆蓋,

我已經修正了 styles.css,加入了 CSS 

min-height: 0

 來強制容器正確計算捲動空間。

請再次 強制重新整理網頁 (Ctrl+Shift+R),現在放大後的圖片應該可以正常捲動了。

gemini 3 pro 一直號稱可以正常顯示, 實際並沒有.


提示詞: (附註: 這裡 Model 使用 gemini 3 pro High)

修改預覽不用顯示原圖 100%, 只需 fit window width.

好的,我理解您的需求。您希望在點擊圖片放大預覽時,不要顯示原始的 100% 尺寸(這可能會太大需要左右捲動),而是讓圖片寬度填滿視窗(Fit Width),只需上下捲動即可查看整張圖片。

我會修改 CSS 設定,將放大後的行為改為「適應寬度」。

我已經修改完成,現在點擊放大預覽時,圖片將會強制填滿視窗寬度(Fit Width),方便您上下捲動檢視,而不會超出螢幕寬度。

重新整理網頁 (Ctrl+Shift+R) 來套用變更。

修改摘要:

  1. CSS 更新:將放大後的寬度樣式從 width: auto 改為 width: 100%
  2. 提示文字更新:更改為「點擊圖片切換寬度適應 (Fit Width)」。

實際上, 這個改動, 也是失敗的, 還是看不到浮水印.


提示詞: (附註: 這裡 Model 使用 gemini 3 pro High)

浮水印沒有移除成功

了解!看來 Gemini 浮水印並非完全貼齊圖片邊緣,而是有一定的偏移量 (padding/margin)。

讓我查看參考實作中浮水印的確切位置:

讓我直接查看 journey-ad 專案的原始碼,找出浮水印的確切偏移量:

Read page
banana.ovo.re

View Page
讓我查看技術文章來了解浮水印的確切位置:

Read page
allenkuo.medium.com

View Page
讓我直接查看 GeminiWatermarkTool 的原始碼來找到偏移量:

Read page
raw.githubusercontent.com

View Page
Preview
Find Watermark Offset Values
Expand
Goal
Navigate to https://github.com/allenk/GeminiWatermarkTool/blob/main/src/WatermarkRemover.cpp

Look for any constants related to:

  • Watermark position offset
  • Padding from edge
  • OFFSET_X, OFFSET_Y
  • MARGIN
  • Position calculations

Opened URL in Browser
https://github.com/allenk/GeminiWatermarkTool/blob/main/src/WatermarkRemover.cpp

Opened URL in Browser
GeminiWatermarkTool/src at main · allenk/GeminiWatermarkTool · GitHub

Extracted DOM elements
GeminiWatermarkTool/src at main · allenk/GeminiWatermarkTool · GitHub

Opened URL in Browser
GeminiWatermarkTool/src/watermark_engine.cpp at main · allenk/GeminiWatermarkTool · GitHub

Read Browser Page in Browser
GeminiWatermarkTool/src/watermark_engine.cpp at main · allenk/GeminiWatermarkTool · GitHub

Extracted DOM elements
GeminiWatermarkTool/src/watermark_engine.cpp at main · allenk/GeminiWatermarkTool · GitHub

Opened URL in Browser
GeminiWatermarkTool/src/watermark_engine.hpp at main · allenk/GeminiWatermarkTool · GitHub

Read Browser Page in Browser
GeminiWatermarkTool/src/watermark_engine.hpp at main · allenk/GeminiWatermarkTool · GitHub

Extracted DOM elements
GeminiWatermarkTool/src/watermark_engine.hpp at main · allenk/GeminiWatermarkTool · GitHub

Opened URL in Browser
GeminiWatermarkTool/src/main.cpp at main · allenk/GeminiWatermarkTool · GitHub

Read Browser Page in Browser
GeminiWatermarkTool/src/main.cpp at main · allenk/GeminiWatermarkTool · GitHub

Extracted DOM elements
GeminiWatermarkTool/src/main.cpp at main · allenk/GeminiWatermarkTool · GitHub

I have successfully analyzed the source code of the GeminiWatermarkTool repository (specifically in src/watermark_engine.cpp and src/watermark_engine.hpp) to determine the exact positioning logic for the Gemini watermark.

Watermark Positioning Rules
The watermark size and position are determined by the image dimensions. Gemini uses two configurations: Small and Large.

  1. Watermark Types & Sizes
    Small Watermark: 48 x 48 pixels.
    Large Watermark: 96 x 96 pixels.
  2. Threshold for Selection
    The tool selects the watermark size based on the following logic:

Large (96×96): Used only if BOTH width and height are strictly greater than 1024px.
Small (48×48): Used in all other cases (including exactly 1024×1024).

  1. Exact Margins and Offsets
    The watermark is not flush with the bottom-right corner. It has specific margins (padding from the edges):

Small Margin: 32 pixels from the right edge and 32 pixels from the bottom edge.
Large Margin: 64 pixels from the right edge and 64 pixels from the bottom edge.
Code Snippets from watermark_engine.cpp
The exact constants and calculations used in the reference tool are as follows:

cpp
// Logic for selecting size and margins
WatermarkPosition get_watermark_config(int image_width, int image_height) {
// Gemini’s rules:
if (image_width > 1024 && image_height > 1024) {
// Large (96×96, 64px margin)
return WatermarkPosition{
.margin_right = 64,
.margin_bottom = 64,
.logo_size = 96
};
} else {
// Small (48×48, 32px margin)
return WatermarkPosition{
.margin_right = 32,
.margin_bottom = 32,
.logo_size = 48
};
}
}
// Top-left coordinate calculation (from watermark_engine.hpp)
cv::Point get_position(int image_width, int image_height) const {
return cv::Point(
image_width – margin_right – logo_size,
image_height – margin_bottom – logo_size
);
}
Summary of Coordinates (Top-Left)
Small Images (<= 1024×1024): X = Width – 32 – 48 = Width – 80 Y = Height – 32 – 48 = Height – 80 Large Images (> 1024×1024):
X = Width – 64 – 96 = Width – 160
Y = Height – 64 – 96 = Height – 160
The issue in the current implementation was likely omitting these 32px / 64px margins, causing the watermark removal to be applied to the wrong area (too close to the corner).

Playback available
太棒了!找到了確切的偏移量!

根據 GeminiWatermarkTool 的原始碼,Gemini 浮水印的位置規則如下:

圖片尺寸遮罩大小邊距 (Margin)起始位置計算
寬高都 > 102496×9664pxX = Width - 64 - 96Y = Height - 64 - 96
其他情況48×4832pxX = Width - 32 - 48Y = Height - 32 - 48

現在我要修正
app.js
中的位置計算和尺寸偵測邏輯:

Analyzed
app.js#L195

已修正浮水印位置計算!

根據 GeminiWatermarkTool 的原始碼,我做了以下修正:

1. 遮罩選擇邏輯

  • 原本min(width, height) >= 1024 → 使用 96px 遮罩
  • 修正後width > 1024 && height > 1024 → 兩邊要大於 1024 才使用 96px 遮罩

2. 新增邊距 (Margin)

  • 48px 遮罩:距離右下角 32px 邊距
  • 96px 遮罩:距離右下角 64px 邊距

位置計算公式

startX = 圖片寬度 - 邊距 - 遮罩尺寸startY = 圖片高度 - 邊距 - 遮罩尺寸

例如一張 1024×1024 的圖片會使用 48px 遮罩:

  • startX = 1024 - 32 - 48 = 944
  • startY = 1024 - 32 - 48 = 944

提示詞: Model 使用 Claude Opus 4.5 (Thinking)

修正preview 時, 原圖 overflow hidden 的問題.

讓我檢查並修正預覽視窗的 overflow 問題:

Analyzedstyles.css#L556-700

我看到問題了。

.modal-content

 設定了 

overflow: hidden

,而且 

.modal-image-container

 的高度也沒有正確繼承。我需要修正這些樣式讓內容可以正確捲動:

Editedstyles.css

+6-3

已修正預覽視窗的 overflow 問題!

修改內容:

  1. .modal-content
    • 改用 display: flex + flex-direction: column
    • 設定明確的 width: 90vw 和 height: 90vh(而不是 max-width/max-height)
    • 這樣內部的 flex 子元素可以正確計算高度
  2. .modal-image-container
    • 將 height: 100% 改為 flex: 1
    • 這讓容器可以自動填滿剩餘空間,並正確傳遞高度給 .modal-viewport

現在無論是「原圖」還是「處理後」的預覽,都應該可以正確捲動了。

請重新整理網頁 (Ctrl+Shift+R) 測試!


這個專案的 token 使用量

使用掉 15.5% 的 Claude Sonnet 4.5 Quotas, Gemini 3 Pro 使用量 5.6%.

建議: 簡單的任務可以先丟給 Gemini 3 Pro, 萬一遇到號稱解決了, 但實際問題還在時, 再使用 Clause Opus 4.5.

Facebook網友回應

您可能也會感興趣的文章...

砧板上的塑膠粉

生活小事

砧板(Cutting board)是很可怕的東西,不要去「刮」他,請用切的,還有超過3年就不要了,比較健康,因為塑膠會脆化,會掉塑膠屑屑,這個砧板,不要買玻璃材質,太滑, […]

Read More

人生最大的成就,是成為你自己

生活小事

如果「人生最大的成就,是成為你自己」的話,那麼,你想成為什麼樣的人? 購書用傳送門:https://www.books.com.tw/products/E05008511 […]

Read More

大谷翔平的說服術

生活小事

前陣子看動漫《我們的重製人生(ぼくたちのリメイク)》,在劇中也可以看到「二刀流」大谷翔平的討論,代表大谷在日職棒就非常的出色,大谷在美國職棒天使隊的重新改寫了很多MLB驚 […]

Read More

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *