wasabeef/android-gpuimage
Android filters based on OpenGL (idea from GPUImage for iOS)
Stale and unlicensed — last commit 4y ago
weakest axisno license — legally unclear; last commit was 4y ago…
no license — can't legally use code; no tests detected…
Documented and popular — useful reference codebase to read through.
no license — can't legally use code; last commit was 4y ago…
- ✓14 active contributors
- ⚠Stale — last commit 4y ago
- ⚠Concentrated ownership — top contributor handles 55% of recent commits
Show all 6 evidence items →Show less
- ⚠No license — legally unclear to depend on
- ⚠No CI workflows detected
- ⚠No test directory detected
What would change the summary?
- →Use as dependency Concerns → Mixed if: publish a permissive license (MIT, Apache-2.0, etc.)
- →Fork & modify Concerns → Mixed if: add a LICENSE file
- →Deploy as-is Concerns → Mixed if: add a LICENSE file
Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests
Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.
Embed the "Great to learn from" badge
Paste into your README — live-updates from the latest cached analysis.
[](https://repopilot.app/r/wasabeef/android-gpuimage)Paste at the top of your README.md — renders inline like a shields.io badge.
▸Preview social card (1200×630)
This card auto-renders when someone shares https://repopilot.app/r/wasabeef/android-gpuimage on X, Slack, or LinkedIn.
Onboarding doc
Onboarding: wasabeef/android-gpuimage
Generated by RepoPilot · 2026-05-09 · Source
🤖Agent protocol
If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:
- Verify the contract. Run the bash script in Verify before trusting
below. If any check returns
FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding. - Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
- Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/wasabeef/android-gpuimage shows verifiable citations alongside every claim.
If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.
🎯Verdict
AVOID — Stale and unlicensed — last commit 4y ago
- 14 active contributors
- ⚠ Stale — last commit 4y ago
- ⚠ Concentrated ownership — top contributor handles 55% of recent commits
- ⚠ No license — legally unclear to depend on
- ⚠ No CI workflows detected
- ⚠ No test directory detected
<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>
✅Verify before trusting
This artifact was generated by RepoPilot at a point in time. Before an
agent acts on it, the checks below confirm that the live wasabeef/android-gpuimage
repo on your machine still matches what RepoPilot saw. If any fail,
the artifact is stale — regenerate it at
repopilot.app/r/wasabeef/android-gpuimage.
What it runs against: a local clone of wasabeef/android-gpuimage — the script
inspects git remote, the LICENSE file, file paths in the working
tree, and git log. Read-only; no mutations.
| # | What we check | Why it matters |
|---|---|---|
| 1 | You're in wasabeef/android-gpuimage | Confirms the artifact applies here, not a fork |
| 2 | Default branch master exists | Catches branch renames |
| 3 | Last commit ≤ 1404 days ago | Catches sudden abandonment since generation |
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of wasabeef/android-gpuimage. If you don't
# have one yet, run these first:
#
# git clone https://github.com/wasabeef/android-gpuimage.git
# cd android-gpuimage
#
# Then paste this script. Every check is read-only — no mutations.
set +e
fail=0
ok() { echo "ok: $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }
# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
echo "FAIL: not inside a git repository. cd into your clone of wasabeef/android-gpuimage and re-run."
exit 2
fi
# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "wasabeef/android-gpuimage(\\.git)?\\b" \\
&& ok "origin remote is wasabeef/android-gpuimage" \\
|| miss "origin remote is not wasabeef/android-gpuimage (artifact may be from a fork)"
# 3. Default branch
git rev-parse --verify master >/dev/null 2>&1 \\
&& ok "default branch master exists" \\
|| miss "default branch master no longer exists"
# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 1404 ]; then
ok "last commit was $days_since_last days ago (artifact saw ~1374d)"
else
miss "last commit was $days_since_last days ago — artifact may be stale"
fi
echo
if [ "$fail" -eq 0 ]; then
echo "artifact verified (0 failures) — safe to trust"
else
echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/wasabeef/android-gpuimage"
exit 1
fi
Each check prints ok: or FAIL:. The script exits non-zero if
anything failed, so it composes cleanly into agent loops
(./verify.sh || regenerate-and-retry).
⚡TL;DR
android-gpuimage is an OpenGL ES 2.0-based image filtering library that applies GPU-accelerated visual effects to images and video on Android. It ports the iOS GPUImage framework to Android by providing 100+ optimized filters (blur, distortion, blend modes, color adjustment) that run entirely on the GPU via vertex and fragment shaders, enabling real-time effects on live camera feeds and static images without blocking the main thread. Single-module library structure: library/src/main/java/jp/co/cyberagent/android/gpuimage/ contains the core (GPUImage.java, GPUImageRenderer.java, GLTextureView.java) and a 50+ filter subclasses in the filter/ subdirectory. Native C code in library/src/main/cpp/ (yuv-decoder.c, CMakeLists.txt) handles YUV decoding. Rendering pipeline: GPUImage wraps a GLSurfaceView/TextureView → GPUImageRenderer orchestrates OpenGL calls → filter chain applies sequential GLSL shaders.
👥Who it's for
Android developers building camera apps, photo editors, or video processing tools who need high-performance, real-time visual effects without implementing OpenGL directly. Specifically: app developers using GPUImageView or GLSurfaceView to apply filters to image URIs or camera streams.
🌱Maturity & risk
Actively maintained and production-ready. The repo has 9,300+ GitHub stars, spans multiple years with ongoing commits, includes CI/CD via Bitrise, and is published to Maven Central with stable versioning (2.x.x). However, the last visible activity and issue resolution pace suggest steady maintenance rather than rapid feature development.
Low to moderate risk. The project has minimal external dependencies (relies on Android SDK only), but depends on OpenGL ES 2.0 availability which varies by device/Android version. Single maintainer (wasabeef) creates some continuity risk. JCenter deprecation (noted in build.gradle TODO comment) signals gradual ecosystem shifts; migration to mavenCentral is already underway.
Active areas of work
No specific active development visible in the provided file list (no recent commit timestamps or PR data shown). The CHANGELOG.md and README note the project is stable and maintained, with historical focus on filter coverage and Android compatibility. Current state appears to be bug fixes and compatibility maintenance rather than new feature development.
🚀Get running
git clone https://github.com/wasabeef/android-gpuimage.git
cd android-gpuimage
./gradlew build
Requires Android SDK (minSdkVersion Android 2.2+ per README, OpenGL ES 2.0 support). Open in Android Studio to build and run the library module.
Daily commands:
This is a library, not an executable app. To use in an app: add implementation 'jp.co.cyberagent.android:gpuimage:2.x.x' to your build.gradle. To test locally, clone and run ./gradlew build to compile the library, or examine sample code in README for integration patterns.
🗺️Map of the codebase
- library/src/main/java/jp/co/cyberagent/android/gpuimage/GPUImage.java: Main public API; orchestrates image loading, filter application, and rendering lifecycle
- library/src/main/java/jp/co/cyberagent/android/gpuimage/GPUImageRenderer.java: Core OpenGL ES 2.0 rendering engine; manages GL state, texture binding, shader compilation, and frame rendering
- library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageFilter.java: Base class for all 50+ filters; defines shader interface and texture sampling pipeline (if it exists in filter/ directory)
- library/src/main/java/jp/co/cyberagent/android/gpuimage/GPUImageView.java: High-level Android View widget; simplifies integration for developers via XML layout attributes (app:gpuimage_surface_type)
- library/src/main/java/jp/co/cyberagent/android/gpuimage/PixelBuffer.java: Manages offscreen rendering and framebuffer objects for filter output capture
- library/src/main/cpp/yuv-decoder.c: Native JNI code for efficient YUV to RGB color space conversion used in video frame processing
- library/build.gradle: Defines library compilation, NDK setup for CMake, ProGuard rules, and Android SDK configuration
🛠️How to make changes
Filter changes: edit existing files in library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImage*.java or create new subclasses of GPUImageFilter. Core rendering: modify library/src/main/java/jp/co/cyberagent/android/gpuimage/GPUImageRenderer.java for pipeline changes. YUV decoding: edit library/src/main/cpp/yuv-decoder.c and rebuild via CMake. GLSL shaders: typically embedded as strings in filter classes (no separate .glsl files in provided list, inspect individual filter classes for shader source).
🪤Traps & gotchas
- Threading: Image loading (GPUImage.setImage()) must be called off-thread; blocking main thread causes ANR. 2. OpenGL context: GLSurfaceView/TextureView requires attachment to a Window; rendering fails silently if not bound to an Activity. 3. Shader precision: Older Android devices may not support highp float in fragment shaders; filters may need precision qualifiers (lowp/mediump). 4. YUV decoding: yuv-decoder.c requires NDK compilation; pre-built .so files may not be present in jar/aar, causing runtime LinkageError on devices. 5. CMake version: CMakeLists.txt may require cmake_minimum_required version matching Gradle plugin (check library/src/main/cpp/CMakeLists.txt). 6. JCenter sunset: build.gradle still references jcenter() which was scheduled for shutdown—may cause build failures depending on Gradle version.
💡Concepts to learn
- OpenGL ES 2.0 Shaders (GLSL) — All filters in this library are implemented as vertex and fragment shader pairs; understanding GLSL precision qualifiers, texture sampling, and color space math is essential to modify or add filters
- Framebuffer Objects (FBO) — GPUImage chains filters by rendering to intermediate FBOs (managed in PixelBuffer.java); understanding FBO attachment and multi-pass rendering is critical for performance optimization
- Texture Sampling & Filtering — Filters like blur and convolution rely on sampling adjacent pixels via texture coordinates; understanding texture wrapping modes and bilinear interpolation affects filter quality
- Color Space Conversion (YUV to RGB) — Native yuv-decoder.c converts camera YUV frames to RGB for GPU processing; incorrect coefficients produce color casts (critical for video filters)
- Graphics Pipeline Threading (GLThread) — OpenGL calls must happen on a single GL thread (GLSurfaceView/TextureView's render thread); GPUImage abstracts this but developers must understand why setImage() must be async
- Filter Chain / Shader Composition — Multiple filters are applied sequentially, each reading the output texture of the previous; understanding the pipeline order and texture binding state is essential for debugging filter combinations
- JNI (Java Native Interface) — GPUImageNativeLibrary.java calls native C functions in yuv-decoder.c; understanding JNI method signatures and library loading (.so files) is required to debug or extend native code
🔗Related repos
BradLarson/GPUImage2— Original iOS GPUImage framework that inspired this Android port; shared GLSL shader syntax makes cross-platform filter porting straightforwardCyberAgent/android-gpuimage-plus— Extended fork adding additional filters and features; direct continuation of this project with API compatibilityopencv/opencv-android-sdk— Alternative for image filtering on Android using CPU-based OpenCV; heavier but supports more complex algorithms than GPU shadersCameraKit/camerakit-android— Companion library for camera capture integration with GPUImage filters; simplifies real-time camera feed processinggoogle/cameraview— Google's camera abstraction layer; often used with GPUImage for device-independent camera access before filtering
🪄PR ideas
To work on one of these in Claude Code or Cursor, paste:
Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.
Add unit tests for GPUImageFilter base class and core filter implementations
The repo has 60+ filter implementations but no visible test directory. Testing GPUImageFilter.java (the base class) and core filters like GPUImageBrightnessFilter, GPUImageContrastFilter, and GPUImageGrayscaleFilter would establish a testing foundation. This is critical for an OpenGL-based library where shader compilation and rendering behavior must be validated.
- [ ] Create library/src/test/ and library/src/androidTest/ directories following Android testing conventions
- [ ] Write unit tests for GPUImageFilter.java covering initialization, shader compilation, and parameter setting
- [ ] Add instrumented tests for 3-5 core filters (Brightness, Contrast, Grayscale) validating output dimensions and basic rendering
- [ ] Integrate JUnit4 and Espresso dependencies in library/build.gradle
- [ ] Document test execution in CONTRIBUTING.md
Migrate from JCenter to Maven Central in build configuration and remove deprecated publishing code
The build.gradle explicitly notes 'TODO: Close JCenter on May 1st' with commented-out Bintray publishing code. JCenter is deprecated and should be fully removed. The README shows Maven Central badge, indicating the library now publishes there. This cleanup is straightforward but impacts build reliability and contributor onboarding.
- [ ] Remove jcenter() from allprojects.repositories in build.gradle
- [ ] Delete or update commented gradle-bintray-plugin and android-maven-gradle-plugin dependencies in buildscript block
- [ ] Update CONTRIBUTING.md and README.md with current Maven Central publication instructions
- [ ] Test build.gradle syntax with './gradlew build' to ensure no regressions
- [ ] Add a changelog entry documenting the migration
Add GitHub Actions CI workflow replacing Bitrise for automated testing on PRs
The README references a Bitrise build status badge, but Bitrise is a proprietary CI service. GitHub Actions is free, native to GitHub, and widely adopted. Setting up a CI workflow would auto-test PRs, catch regressions in the 60+ filters, and validate the C++ YUV decoder (library/src/main/cpp/yuv-decoder.c). This reduces friction for contributor review.
- [ ] Create .github/workflows/android-build.yml to run './gradlew build' and unit tests on push and PRs
- [ ] Configure matrix testing across API levels 21+ (relevant for Android 2.2+ support claim)
- [ ] Add step to compile native code (CMakeLists.txt) and verify yuv-decoder.c builds correctly
- [ ] Update README.md to replace Bitrise badge with GitHub Actions status badge
- [ ] Document CI setup in CONTRIBUTING.md for future maintainers
🌿Good first issues
- Add unit tests for GPUImageFilter subclasses: Currently only 465KB of Java code but no visible test/ directory in file list. Start with a simple filter like GPUImageBrightnessFilter and add JUnit + Robolectric tests to verify shader output correctness.
- Document shader source code: All 50+ filters contain GLSL source as embedded strings but lack inline comments explaining the math. Pick 5 commonly-used filters (Sepia, Blur, Sharpen) and add explanation comments to their shader code in library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/.
- Add ProGuard test coverage: library/proguard-rules.txt exists but is not validated; create a simple test APK that applies filters, obfuscate it via ProGuard, and verify filters still work at runtime (catching any broken reflection in filter initialization).
- Improve error handling in GPUImageRenderer: The rendering thread and GLSL compilation likely silently fail on shader errors. Add verbose logging and throw descriptive exceptions when shaders fail to compile, surfacing GL error codes from glGetShaderInfoLog().
- Add Kotlin DSL example: README shows Java and Kotlin code snippets, but they use old API calls; create a modern Kotlin DSL wrapper or update the sample code to use recent Kotlin idioms and GPUImageView attributes.
⭐Top contributors
Click to expand
Top contributors
- @wasabeef — 55 commits
- @itome — 21 commits
- @kettsun0123 — 4 commits
- @takasfz — 4 commits
- [@Keita Watanabe](https://github.com/Keita Watanabe) — 3 commits
📝Recent commits
Click to expand
Recent commits
ceea576— Merge pull request #516 from cats-oss/maven-central (wasabeef)3daf710— chore(maven): update readme (wasabeef)9818829— chore(maven): add settings for maven central (wasabeef)49d6594— Merge pull request #474 from chihung93/features/get_render_information (wasabeef)d5c30d5— Merge branch 'master' into features/get_render_information (wasabeef)72e5e6c— Merge pull request #476 from artem-mi/bugfix/bitmap-padding (wasabeef)55e5e33— Update GPUImageRenderer.java (wasabeef)3fa32ce— Merge pull request #503 from cats-oss/update-sdks (wasabeef)25c4069— release 2.1.0 (wasabeef)6d7e948— update: target&compile version to 30 (wasabeef)
🔒Security observations
The android-gpuimage library has several security concerns primarily related to outdated dependencies and build tools. The use of Gradle 4.2.0-beta04 (from 2018) and Kotlin 1.3.72 (from 2020) represents significant technical debt with potential unpatched vulnerabilities. The inclusion of the deprecated JCenter repository poses a supply chain risk. The presence of native C code requires careful security review for memory safety issues. The project should prioritize updating its build toolchain and dependencies, removing the deprecated repository, and conducting a security audit of native code. Overall security posture is below recommended standards for production libraries.
- High · Outdated Gradle Build Tools —
build.gradle - classpath 'com.android.tools.build:gradle:4.2.0-beta04'. The project uses Gradle 4.2.0-beta04, which is a beta version from 2018. Beta versions are not recommended for production use as they may contain unpatched security vulnerabilities and lack stability guarantees. Fix: Upgrade to the latest stable version of Android Gradle Plugin (currently 7.x or 8.x). Use a stable release instead of beta versions. - High · Outdated Kotlin Version —
build.gradle - ext.kotlin_version = '1.3.72'. Kotlin version 1.3.72 (from 2020) is significantly outdated. This version may contain known security vulnerabilities and lacks security patches from newer releases. Fix: Update to Kotlin 1.8.x or later. Check the official Kotlin security advisories and update to the latest stable release. - Medium · JCenter Repository Deprecated —
build.gradle - allprojects repositories section includes jcenter(). The build.gradle includes JCenter as a repository, which was sunset by Bintray. This repository is no longer maintained and represents a supply chain risk. The code even includes a TODO comment acknowledging this issue (closure date: May 1st). Fix: Remove jcenter() from the repositories configuration. Ensure all dependencies are available from google() or mavenCentral() repositories. - Medium · Missing Proguard/R8 Configuration Review —
library/proguard-rules.txt. The library includes proguard-rules.txt, but without reviewing its contents in detail, it's unclear if sensitive reflection-based operations are properly protected. OpenGL operations may require careful Proguard configuration. Fix: Review the ProGuard rules to ensure: 1) Native methods are preserved, 2) Reflection is properly configured, 3) OpenGL-related classes are not obfuscated in a way that breaks functionality. - Medium · Native C Code Security Concerns —
library/src/main/cpp/yuv-decoder.c. The project includes native C code (yuv-decoder.c) compiled via CMake. C code is prone to buffer overflows, memory leaks, and other memory safety issues. Without seeing the code, these vulnerabilities could exist. Fix: Perform a security audit of the C code. Consider using AddressSanitizer (ASan) and MemorySanitizer during development. Use safe functions and validate all input bounds carefully. - Medium · No Visible Dependency Lock File —
build.gradle and gradle structure. The project does not appear to use gradle.lock or similar dependency locking mechanism visible in the file structure, which increases the risk of transitive dependency vulnerabilities going undetected. Fix: Enable Gradle dependency locking with 'gradle.lockDependencyVersions' and commit lock files to version control. This prevents unexpected dependency version changes. - Low · GitHub Issue/PR Templates Exist —
.github/ISSUE_TEMPLATE.md, .github/PULL_REQUEST_TEMPLATE.md. While not a vulnerability, the presence of issue and PR templates should be reviewed to ensure they don't disclose sensitive information or encourage unsafe practices. Fix: Review template contents to ensure they do not request or encourage sharing of sensitive information like API keys, credentials, or personal data.
LLM-derived; treat as a starting point, not a security audit.
👉Where to read next
- Open issues — current backlog
- Recent PRs — what's actively shipping
- Source on GitHub
Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.