Skip to content

feat: add WebP + AVIF output encoding (pure-Go, no cgo)#500

Open
trungnsbkvn wants to merge 9 commits into
willnorris:mainfrom
trungnsbkvn:main
Open

feat: add WebP + AVIF output encoding (pure-Go, no cgo)#500
trungnsbkvn wants to merge 9 commits into
willnorris:mainfrom
trungnsbkvn:main

Conversation

@trungnsbkvn

Copy link
Copy Markdown

Upstream imageproxy decodes WebP but only encodes JPEG/PNG/GIF/TIFF/BMP
(issue #114). This fork adds WebP + AVIF encoders via gen2brain/webp and
gen2brain/avif (libwebp/libaom compiled to WASM, run by wazero) so the
single static binary — built with CGO_ENABLED=0, native Windows — can emit
modern formats for luatsumienbac.vn's self-hosted /media resizer.

trungnsbkvn and others added 2 commits July 1, 2026 19:26
Upstream imageproxy decodes WebP but only encodes JPEG/PNG/GIF/TIFF/BMP
(issue willnorris#114). This fork adds WebP + AVIF encoders via gen2brain/webp and
gen2brain/avif (libwebp/libaom compiled to WASM, run by wazero) so the
single static binary — built with CGO_ENABLED=0, native Windows — can emit
modern formats for luatsumienbac.vn's self-hosted /media resizer.

- data.go: register webp/avif as parseable format options
- transform.go: webp/avif encode cases + contentTypeForFormat() + defaults
- imageproxy.go: set explicit Content-Type for known formats (Go's
  http.DetectContentType has no AVIF signature -> would 403 as octet-stream)
- go.mod: + gen2brain/webp, gen2brain/avif (pure-Go WASM, no cgo)

Verified: CGO_ENABLED=0 build + runtime smoke test emits valid
image/avif (ftypavif) and image/webp (RIFF/WEBP).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Build (native + cross-compile), run as a service (NSSM on Windows, systemd
on Linux with hardening), reverse proxy (IIS URL Rewrite+ARR, nginx, Caddy —
all stripping /img), disk + Cloudflare caching, optional HMAC signing, and a
troubleshooting table. Flags/behaviour verified against cmd/imageproxy.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@willnorris

Copy link
Copy Markdown
Owner

Did you mean to include all the docs that look to be specific to your fork? I'm guess not?

There's some discussion about webp in #388, and I have an experimental webp branch using a different library. I'm not familiar with this one, but will take a look when I get a chance. I think the last one I tried ended up creating files much larger than their JPEG equivalent, so missed all the actual advatnages of webp.

@trungnsbkvn

Copy link
Copy Markdown
Author

My bad,

Not the docs. I was working with my Astro project and found your brilliant work.

trungnsbkvn and others added 7 commits July 2, 2026 10:59
- build.ps1: build build/imageproxy.exe (CGO_ENABLED=0, windows/amd64) + smoke test
- build/install-service.ps1, uninstall-service.ps1: NSSM service (PS 5.1+ compatible)
- build/run.ps1: foreground run for testing
- build/config.example.env: IMAGEPROXY_* env alternative to flags
- build/README.md: copy-to-server deploy checklist -> DEPLOY.md
- .gitignore: ignore built *.exe and *.log (scripts are tracked)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…bwebp, WebP-only)

willnorris#393 is unmerged, WebP-only, and cgo-bound to C libwebp (breaks the
single-binary / native-Windows / no-deps goal). Our gen2brain WASM approach
stays CGO_ENABLED=0 and adds AVIF. Trade-off: slower encode, mitigated by cache.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
nssm is an external dependency (and its site can be down). Make the single
binary register ITSELF with the OS service manager instead:

- cmd/imageproxy/service.go (new): -service install|uninstall|start|stop|restart
  (Windows SCM / systemd / launchd) + -logFile (service stdout is discarded).
  Foreground behaviour unchanged; graceful shutdown on Stop.
- cmd/imageproxy/main.go: build the http.Server then runWithService(server).
- go.mod: + github.com/kardianos/service (pure Go, keeps CGO_ENABLED=0).
- build/install-service.ps1 + uninstall-service.ps1: rewritten to use the
  binary's -service (no nssm); install adds sc.exe crash-restart + auto-start.
- DEPLOY.md / build/README.md / FORK_NOTES.md: nssm -> native service.

Verified: CGO_ENABLED=0 windows build; foreground health-check OK; -service
control wired (lists valid actions); -logFile captures startup + errors.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
nssm is available again, so keep it as an option alongside the native
self-install (native stays the default — no dependency).

- install-service.ps1: -Method native|nssm (default native). nssm branch
  quotes paths, sets AppExit Restart + auto-start; native branch unchanged.
- uninstall-service.ps1: generic sc.exe stop+delete — removes either kind.
- DEPLOY.md / build/README.md: document both methods; FORK_NOTES clarifies
  nssm still works as an external wrapper.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…poll)

The old trailing-& background job raced the health check ('(smoke test
skipped)') and could leak the process. Now starts hidden with -PassThru,
polls /health-check up to 6s, and stops that exact process.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- install-service.ps1: add optional -NssmPath so nssm need not be on PATH.
- DEPLOY.md: acquisition (choco/scoop/manual zip -> win64\nssm.exe),
  by-hand configuration + what each nssm setting means, graceful-stop and
  run-as-account notes.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ssm args

Reported: 'nssm.exe : Can't open service!' aborted install-service.ps1 on a
fresh install. Root cause: PowerShell 7.4+ throws on a native command's
non-zero exit under ErrorActionPreference='Stop', so the pre-cleanup 'nssm
stop' of a not-yet-installed service was fatal.

- install/uninstall/build .ps1: set $PSNativeCommandUseErrorActionPreference
  = $false (harmless on PS 5.1); keep explicit $LASTEXITCODE checks.
- install-service.ps1: pass runtime flags to nssm as an ARRAY
  () instead of a hand-quoted AppParameters
  string — fixes spaced/& paths (e.g. 'D:\Webs\2. Youth & Partners\...').
  Cleanup now Get-Service-guarded + sc.exe; verify Running at the end.
- DEPLOY.md: by-hand nssm uses the array form; troubleshooting rows for the
  NativeCommandError and spaced paths (space-free path recommended).

Verified: reproduced the throw with sc.exe on a nonexistent service and
confirmed the flag prevents it; all scripts parse clean.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants