Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
ad279c2
Create build-libwebp.yml
dima-dencep Mar 12, 2026
a80361c
Update build-libwebp.yml
dima-dencep Mar 12, 2026
8d932b9
Update build-libwebp.yml
dima-dencep Mar 12, 2026
9618487
Update build-libwebp.yml
dima-dencep Mar 12, 2026
7834421
Update build-libwebp.yml
dima-dencep Mar 12, 2026
77afe68
Update bundled libwebp v1.6.0
github-actions[bot] Mar 12, 2026
d9a22f1
Update build-libwebp.yml
dima-dencep Mar 12, 2026
21f2245
Update bundled libwebp v1.6.0
github-actions[bot] Mar 12, 2026
6dcd5e4
Update build-libwebp.yml
dima-dencep Mar 12, 2026
9f5717a
Update bundled libwebp v1.6.0
github-actions[bot] Mar 12, 2026
c97e2e8
Update build-libwebp.yml
dima-dencep Mar 12, 2026
1d1a551
Update bundled libwebp v1.6.0
github-actions[bot] Mar 12, 2026
8e8443c
Update build-libwebp.yml
dima-dencep Mar 12, 2026
99e0a14
Update bundled libwebp v1.6.0
github-actions[bot] Mar 12, 2026
38583de
Update build-libwebp.yml
dima-dencep Mar 12, 2026
4610c52
Update bundled libwebp v1.6.0
github-actions[bot] Mar 12, 2026
d8761f2
Update build-libwebp.yml
dima-dencep Mar 12, 2026
9290320
Update bundled libwebp v1.6.0
github-actions[bot] Mar 12, 2026
082f402
Try bundled
dima-dencep Mar 12, 2026
7e31dab
Fix tests
dima-dencep Mar 12, 2026
cdbb7ea
Update build-libwebp.yml
dima-dencep Mar 12, 2026
e952901
Update bundled libwebp v1.6.0
github-actions[bot] Mar 12, 2026
38202bd
Update test-webp.yml
dima-dencep Mar 12, 2026
5efdf09
Final
dima-dencep Mar 12, 2026
ba394a4
Version
dima-dencep Mar 12, 2026
82f0dab
Update TestingApp.java
dima-dencep Mar 12, 2026
6a0ff03
Update renovate.json
dima-dencep Mar 12, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
165 changes: 165 additions & 0 deletions .github/workflows/build-libwebp.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
name: Build libwebp

on:
push:
paths:
- '.github/workflows/build-libwebp.yml'
workflow_dispatch:
inputs:
libwebp_version:
description: 'libwebp version tag (e.g. v1.6.0)'
required: false
default: 'v1.6.0'

env:
LIBWEBP_VERSION: ${{ inputs.libwebp_version || 'v1.6.0' }}

jobs:
build:
strategy:
fail-fast: false
matrix:
include:
- os: ubuntu-latest
target: linux
artifact: libwebp.so
- os: windows-latest
target: windows
artifact: libwebp.dll
- os: macos-latest
target: macos
artifact: libwebp.dylib

name: ${{ matrix.target }}
runs-on: ${{ matrix.os }}

steps:
- uses: actions/checkout@v6

- name: Clone libwebp
run: git clone --depth 1 --branch ${{ env.LIBWEBP_VERSION }} https://chromium.googlesource.com/webm/libwebp

- name: Patch out decoder
shell: bash
run: |
cd libwebp
sed -i.bak 's/\$<TARGET_OBJECTS:webpdecode>//' CMakeLists.txt
sed -i.bak 's/add_library(sharpyuv /add_library(sharpyuv STATIC /' CMakeLists.txt

- name: Create export lists
shell: bash
run: |
cat > libwebp-exports.txt <<'EOF'
{ global: WebPEncodeLosslessBGRA; WebPFree; local: *; };
EOF
cat > libwebp-exports-macos.txt <<'EOF'
_WebPEncodeLosslessBGRA
_WebPFree
EOF
cat > libwebp-exports.def <<'EOF'
EXPORTS
WebPEncodeLosslessBGRA
WebPFree
EOF

- name: Build (Unix)
if: runner.os != 'Windows'
run: |
cd libwebp
mkdir build && cd build

if [ "${{ matrix.target }}" = "macos" ]; then
EXTRA_FLAGS="-DCMAKE_OSX_ARCHITECTURES=arm64 -DCMAKE_SHARED_LINKER_FLAGS=-Wl,-exported_symbols_list,${{ github.workspace }}/libwebp-exports-macos.txt,-dead_strip"
else
EXTRA_FLAGS="-DCMAKE_SHARED_LINKER_FLAGS=-Wl,--version-script=${{ github.workspace }}/libwebp-exports.txt,--gc-sections"
fi

cmake .. \
-DCMAKE_BUILD_TYPE=MinSizeRel \
-DCMAKE_INTERPROCEDURAL_OPTIMIZATION=ON \
-DCMAKE_C_FLAGS="-ffunction-sections -fdata-sections -fvisibility=hidden -fno-asynchronous-unwind-tables" \
-DBUILD_SHARED_LIBS=ON \
-DWEBP_BUILD_ANIM_UTILS=OFF \
-DWEBP_BUILD_CWEBP=OFF \
-DWEBP_BUILD_DWEBP=OFF \
-DWEBP_BUILD_GIF2WEBP=OFF \
-DWEBP_BUILD_IMG2WEBP=OFF \
-DWEBP_BUILD_VWEBP=OFF \
-DWEBP_BUILD_WEBPINFO=OFF \
-DWEBP_BUILD_WEBPMUX=OFF \
-DWEBP_BUILD_EXTRAS=OFF \
$EXTRA_FLAGS
cmake --build . --target webp --config MinSizeRel
if [ "${{ matrix.target }}" = "macos" ]; then
strip -x libwebp.* 2>/dev/null || true
else
strip -s libwebp.* 2>/dev/null || true
fi

- name: Build (Windows)
if: runner.os == 'Windows'
run: |
cd libwebp
mkdir build && cd build
cmake .. `
-DCMAKE_BUILD_TYPE=MinSizeRel `
-DCMAKE_INTERPROCEDURAL_OPTIMIZATION=ON `
-DCMAKE_C_FLAGS="/Gw /DWEBP_EXTERN=extern" `
-DBUILD_SHARED_LIBS=ON `
-DCMAKE_SHARED_LINKER_FLAGS="/DEF:${{ github.workspace }}/libwebp-exports.def /OPT:REF,ICF" `
-DWEBP_BUILD_ANIM_UTILS=OFF `
-DWEBP_BUILD_CWEBP=OFF `
-DWEBP_BUILD_DWEBP=OFF `
-DWEBP_BUILD_GIF2WEBP=OFF `
-DWEBP_BUILD_IMG2WEBP=OFF `
-DWEBP_BUILD_VWEBP=OFF `
-DWEBP_BUILD_WEBPINFO=OFF `
-DWEBP_BUILD_WEBPMUX=OFF `
-DWEBP_BUILD_EXTRAS=OFF
cmake --build . --target webp --config MinSizeRel

- name: Copy artifact
shell: bash
run: |
mkdir -p output
if [ "${{ matrix.target }}" = "windows" ]; then
cp libwebp/build/MinSizeRel/${{ matrix.artifact }} output/
else
cp libwebp/build/${{ matrix.artifact }} output/
fi

- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: libwebp-${{ matrix.target }}
path: output/${{ matrix.artifact }}

commit:
needs: build
runs-on: ubuntu-latest
permissions:
contents: write

steps:
- uses: actions/checkout@v6

- name: Download all artifacts
uses: actions/download-artifact@v4
with:
path: artifacts

- name: Place natives
run: |
mkdir -p webp/src/main/resources/natives/{linux,windows,macos}
cp artifacts/libwebp-linux/libwebp.so webp/src/main/resources/natives/linux/
cp artifacts/libwebp-windows/libwebp.dll webp/src/main/resources/natives/windows/
cp artifacts/libwebp-macos/libwebp.dylib webp/src/main/resources/natives/macos/

- name: Commit
run: |
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
git add webp/src/main/resources/natives/
git diff --cached --quiet && echo "No changes" && exit 0
git commit -m "Update bundled libwebp ${{ env.LIBWEBP_VERSION }}"
git push
9 changes: 6 additions & 3 deletions .github/workflows/test-webp.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@ name: Test WebP

on:
push:
branches:
- 'main'
paths:
- 'webp/**'
- '.github/workflows/test-webp.yml'
pull_request:
workflow_run:
workflows: [Build libwebp]
types: [completed]
workflow_dispatch:

jobs:
Expand All @@ -25,13 +25,16 @@ jobs:
name: Linux (NgEngine)
install: sudo find /usr -name 'libwebp*.so*' -exec mv {} {}.disabled \;
expected-decode: Java (ngengine)
expected-encode: libwebp (lossless-only)
- os: macos-latest
name: macOS (ImageIO)
expected-decode: macOS ImageIO
expected-encode: libwebp (lossless-only)
- os: windows-latest
name: Windows (WIC)
install: winget install --id 9PG2DK419DRG --accept-package-agreements --accept-source-agreements --source msstore --silent
expected-decode: Windows WIC
expected-encode: libwebp (lossless-only)

name: ${{ matrix.name }}
runs-on: ${{ matrix.os }}
Expand Down
39 changes: 25 additions & 14 deletions README.MD
Original file line number Diff line number Diff line change
Expand Up @@ -45,14 +45,14 @@ repositories {

dependencies {
// Include only the modules you need:
implementation "org.redlance.platformtools:accent:4.1.1"
implementation "org.redlance.platformtools:referer:4.1.1"
implementation "org.redlance.platformtools:favorites:4.1.1"
implementation "org.redlance.platformtools:progress:4.1.1"
implementation "org.redlance.platformtools:webp:4.1.1"
implementation "org.redlance.platformtools:accent:4.2.0"
implementation "org.redlance.platformtools:referer:4.2.0"
implementation "org.redlance.platformtools:favorites:4.2.0"
implementation "org.redlance.platformtools:progress:4.2.0"
implementation "org.redlance.platformtools:webp:4.2.0"

// For Java 8 (Downgraded version), add classifier:
// implementation("org.redlance.platformtools:accent:4.1.1:java8")
// implementation("org.redlance.platformtools:accent:4.2.0:java8")
}
```

Expand All @@ -69,7 +69,7 @@ dependencies {
<dependency>
<groupId>org.redlance.platformtools</groupId>
<artifactId>accent</artifactId>
<version>4.1.1</version>
<version>4.2.0</version>
</dependency>
```

Expand Down Expand Up @@ -205,16 +205,27 @@ Decoder priority (first available wins):
3. **Windows WIC** — Windows Imaging Component via FFM (decode only, requires WebP codec from MS Store)
4. **ngengine** — pure-Java fallback ([image-webp-java](https://github.com/NostrGameEngine/image-webp-java), decode only, ~92 KB bundled)

The `webp` module has two variants:
- **Standard** (`webp`) — uses platform-native APIs or system-installed libwebp. Zero bundled dependencies.
- **Bundled** (`webp` with classifier `bundled`) — includes a shaded and ProGuard-optimized [ngengine image-webp-java](https://github.com/NostrGameEngine/image-webp-java) decoder (~92 KB). Pixel-exact on all platforms without native libraries.
Encoder priority:
1. **libwebp** — system-installed native library (lossy + lossless)
2. **libwebp (lossless-only)** — bundled native encoder (lossless only, included in standard and `bundled` variants)

The `webp` module has three variants:

| Variant | Classifier | Natives | ngengine | Use case |
|---------|------------|---------|----------|----------|
| **Standard** | — | bundled libwebp (lossless encoder) | — | Platform with native decoder (macOS/Windows) or system libwebp |
| **Bundled** | `bundled` | bundled libwebp (lossless encoder) | shaded + ProGuard | Self-contained, works everywhere |
| **Bundled Lite** | `bundled-lite` | — | shaded + ProGuard | Minimal size, no native binaries |

```groovy
// Standard — requires platform support or libwebp on library path
implementation "org.redlance.platformtools:webp:4.1.1"
// Standard — bundled lossless encoder, requires platform decoder or system libwebp for decoding
implementation "org.redlance.platformtools:webp:4.2.0"

// Bundled — self-contained with ngengine decoder + bundled lossless encoder
implementation "org.redlance.platformtools:webp:4.2.0:bundled"

// Bundled — self-contained, works everywhere (decode only)
implementation "org.redlance.platformtools:webp:4.1.1:bundled"
// Bundled Lite — ngengine decoder only, no native binaries
implementation "org.redlance.platformtools:webp:4.2.0:bundled-lite"
```

```java
Expand Down
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ plugins {

allprojects {
group = "org.redlance"
version = "4.1.1"
version = "4.2.0"

repositories {
mavenCentral()
Expand Down
9 changes: 9 additions & 0 deletions renovate.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,14 @@
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": [
"config:recommended"
],
"customManagers": [
{
"customType": "regex",
"fileMatch": ["\\.github/workflows/build-libwebp\\.yml$"],
"matchStrings": ["'(?<currentValue>v\\d+\\.\\d+\\.\\d+)'"],
"depNameTemplate": "webmproject/libwebp",
"datasourceTemplate": "github-tags"
}
]
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import org.redlance.platformtools.favorites.PlatformFinderFavorites;
import org.redlance.platformtools.progress.PlatformProgressBars;
import org.redlance.platformtools.referer.PlatformFileReferer;
import org.redlance.platformtools.webp.WebPDiagnostics;
import org.redlance.platformtools.webp.decoder.DecodedImage;
import org.redlance.platformtools.webp.decoder.PlatformWebPDecoder;
import org.redlance.platformtools.webp.encoder.PlatformWebPEncoder;
Expand Down Expand Up @@ -311,6 +312,10 @@ private void showWebPDialog() {
}

log.append("\n");
WebPDiagnostics.summary(s -> {
log.append(s);
log.append("\n");
});
});
buttons.add(probeBtn);

Expand Down
13 changes: 12 additions & 1 deletion webp/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,14 @@ tasks.register("proguardJar", ProGuardTask) {
configuration(file("proguard.pro"))
}

assemble.dependsOn proguardJar
tasks.register("bundledLiteJar", Jar) {
dependsOn proguardJar
from(zipTree(proguardJar.getOutJarFileCollection().singleFile))
exclude 'natives/**'
archiveClassifier.set("bundled-lite")
}

assemble.dependsOn proguardJar, bundledLiteJar
downgradeJar.enabled = false

shadow {
Expand All @@ -82,4 +89,8 @@ publishing.publications.named("mavenJava") {
classifier = "bundled"
builtBy(tasks.named("proguardJar"))
}
artifact(tasks.named("bundledLiteJar")) {
classifier = "bundled-lite"
builtBy(tasks.named("bundledLiteJar"))
}
}
Loading