Metadata-Version: 2.4
Name: gemini-logo-remover
Version: 0.1.0
Summary: Remove the Gemini watermark from images with one function call, using the Gemini Logo Remover API.
License: MIT
Project-URL: Homepage, https://app.gemini-logo-remover.workers.dev
Project-URL: Documentation, https://app.gemini-logo-remover.workers.dev/developers
Keywords: gemini,watermark,logo,remover,image,ai
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: Multimedia :: Graphics
Classifier: Typing :: Typed
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: requests>=2.28
Requires-Dist: Pillow>=9.0
Provides-Extra: dev
Requires-Dist: pytest>=7; extra == "dev"
Requires-Dist: build; extra == "dev"
Requires-Dist: twine; extra == "dev"
Dynamic: license-file

# gemini-logo-remover

Remove the Gemini watermark from images with one function call.

```bash
pip install gemini-logo-remover
```

```python
from gemini_logo_remover import remove_logo

remove_logo("gemini-image.png", "clean.png")
```

## How it works

The watermark only sits in the bottom-right corner. This package cuts out that corner
(at most 480×480 px), sends **only that small piece** to the Gemini Logo Remover API,
and pastes the cleaned corner back into your original image on your machine.

- Uploads are tiny (a few hundred KB), so it is fast.
- Every pixel outside the corner is returned exactly as it was — the server never
  re-compresses your picture.
- The removal itself runs on the hosted API (a Cloudflare Worker), not on your computer.
  Your images are not stored; only the corner crop is sent.

The server reverses the watermark's alpha blend (lossless) and falls back to AI inpainting
only for what that cannot explain.

## Usage

### One image

```python
from gemini_logo_remover import remove_logo

result = remove_logo("in.png", "out.png")        # saves out.png
print(result.method, result.clean, result.warnings)

# no file written, work with the Pillow image instead
result = remove_logo("in.png")
result.image.show()
result.save("later.jpg")                          # .jpg -> JPEG, otherwise PNG
```

`image` can be a path, `bytes`, an open binary file, or a `PIL.Image`.

`Result` fields: `image`, `method` (`alpha`, `inpaint`, `alpha+inpaint`, `none`),
`detected`, `slot`, `confidence`, `clean`, `warnings`, `output_path`.

### Many images, in parallel

```python
from gemini_logo_remover import remove_logo_many

items = remove_logo_many(["a.png", "b.png", "c.jpg"], "cleaned/", workers=3)
for item in items:
    print(item.source, "ok" if item.ok else f"failed: {item.error}")
```

One bad file never stops the others; failures are returned in the list. Keep `workers`
at 3 or less on the free hosted API.

### Command line

```bash
gemini-logo-remover photo.png                     # writes photo_clean.png next to it
gemini-logo-remover *.png -o cleaned/ --workers 3
gemini-logo-remover photo.png --mode alpha        # lossless only
python -m gemini_logo_remover photo.png           # same thing
```

### Options

| Option | Default | Meaning |
| --- | --- | --- |
| `mode` | `auto` | `auto`: reverse the watermark, inpaint only what is left. `alpha`: lossless only, never inpaints (image unchanged + a warning if it cannot). `inpaint`: skip alpha. |
| `sparkle` | `False` | Also inpaint the small V3 slot. Unverified; can damage text near the corner. |
| `api_url` | hosted API | Your own server. Or set `GEMINI_LOGO_REMOVER_API_URL`. |
| `api_key` | none | If the server requires a key. Or set `GEMINI_LOGO_REMOVER_API_KEY`. |
| `retries` | `3` | Extra attempts on 429 / 5xx / network errors / cut-off replies. |
| `timeout` | `180` | Seconds per request. |

### Errors

- `InvalidImageError` — the input is not a readable image.
- `ApiError` — the API rejected the request or kept failing. Has `.status` and `.code`.
- `GeminiLogoRemoverError` — base class of both.

## Limits

The hosted API runs on a free tier. Expect to process a few images at a time, not
thousands. Point `api_url` at your own deployment of the server for heavy use.

## Development and publishing

```bash
cd python
pip install -e ".[dev]"
pytest

python -m build                      # creates dist/*.whl and dist/*.tar.gz
twine check dist/*
twine upload --repository testpypi dist/*   # try it on TestPyPI first
twine upload dist/*                         # publish to PyPI
```

Uploading needs a PyPI account and an API token (pypi.org → Account settings → API tokens);
use `__token__` as the username and the token as the password. Bump `version` in
`pyproject.toml` (and `__version__`) for every release — PyPI never lets you re-upload the
same version.
