fix(avatar-pack): bg removal, style regen consistency, and doc restructure#20
fix(avatar-pack): bg removal, style regen consistency, and doc restructure#20
Conversation
Cola-only skill that generates pixel-art avatars, profile cards, 4 emoji GIFs (happy/sad/angry/thinking) and 3 meme stickers (confused/annoyed/cracked). Includes HARD-GATE environment check so non-Cola agents get a clear message instead of silent failure. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
GENERATE.md: - Add grid/checkerboard keywords to negative_prompt to reduce background artifacts - Improve Phase 5.5 quality check: add outfit color consistency check, smarter retry (use solid white bg + enforce reference matching on retry) - Fix scene C single-expression regen: pass --line1/--line2 so profile card renders correctly process_avatar.py: - Better background removal: detect and clean grid line remnants on semi-transparent images using a 15x15 window scan (>80% transparent neighbors = remnant) - Raise corner sampling threshold from 50% to 90% to catch checkerboard backgrounds - Extract _is_fringe_color() helper for cleaner fringe detection (catches warm/cool gray, off-white, light beige — not just neutral gray) - Use 8-connected neighbors instead of 4-connected for fringe removal - Iterate fringe removal up to 3 rounds to handle multi-pixel-deep artifacts - Widen lightning bolt crack in "cracked" meme for better visibility Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…d cleanup GENERATE.md: - Add fallback for expired signed URLs in reference_images: re-upload from local base_image_original.png, or append text-based style matching prompt process_avatar.py: - Replace window-scan grid removal with flood-fill from transparent pixels into adjacent neutral/light opaque pixels — more accurate, avoids killing character content that happens to be surrounded by transparency Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Profile tagline (Phase 2.4) must now align with AGENT.md personality — prevents introducing negative traits absent from the character definition (e.g., writing "holds grudges" when the character is "never genuinely mean"). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
… profile card mismatch When user chose "adjust style" (scenario C option 2), save_base_image's guard kept the old base_image_original.png while overwriting base_image.png. Since generate_profile_card prefers original, the card showed old style while expressions showed new style. Now we rm the old original first so the guard lets the new 1K image through. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…pdate tagline example - Add two extra passes in remove_background() to clear semi-transparent neutral pixels and re-flood-fill from newly opened holes, fixing residual checkerboard artifacts from AI generators - Update profile tagline example to better illustrate contradiction Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…, color system refactor - process_avatar.py: auto-detect low-transparency images and call rembg CLI as primary background removal before falling back to flood-fill. Fixes persistent opaque-background bug when listenhub outputs 0% transparent images. - SKILL.md: rewrote description into Use when / Also use when / Do NOT use when structure with English keywords for better skill matching - GENERATE.md: replaced hex codes and vague adjectives with aesthetic-narrative color guidance per wuxing element (e.g. fire → 窑变釉的红 → cinnabar red prompt); avatar.json now written in Phase 4 instead of Phase 7; added Phase 5.0 parameter validation with fallback recalculation if avatar.json missing; updated personality line rules to disallow negative traits absent from AGENT.md definition
…rembg prereq - After rembg removes background, recompute transparency stats so the branch-1 cleanup (flood-fill from transparent pixels) still runs on any residual artifacts rembg left behind - Remove redundant border-seeded flood-fill pass (rembg handles the cases it was designed for) - Add rembg availability check to GENERATE.md prerequisites Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Consolidate trigger phrases into a single compact list and switch the description to English for consistency with the skill metadata format. No behavioral change — same trigger conditions. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
… to GENERATE.md SKILL.md now only contains runtime behavior (wake display, emoji usage). GENERATE.md is self-contained with output rules, file paths, and all generation phases. Also drop "场景 A/B/C/D" labels in favor of plain section names and add explicit "no caption" reminder to meme usage. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…profile card - Initialize tmp_in/tmp_out to None before try block in _try_rembg() to avoid UnboundLocalError in finally if tempfile creation fails - Pass base_output (local processed path) instead of args.base (may be a remote URL) to generate_profile_card so it reads the correct file - Clarify in GENERATE.md that avatar.json is maintained by the outer flow, not by process_avatar.py Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…se_image runs Remove the exists-guard in save_base_image() — the caller (main's is_expression_only check) already skips save_base_image entirely for expression-only regeneration. When save_base_image does run, the input is always a fresh 1K image, so the guard was only preventing style-regen (scenario C option 2) from updating the original. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…gray checkerboard Reduce avg brightness threshold from 160 to 90 in _is_bg_remnant() so the flood-fill cleanup pass can clear medium-gray checkerboard squares that rembg sometimes leaves behind. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Lower _is_bg_remnant avg threshold from 90 to 55 to detect dark checkerboard squares (~70 brightness) while preserving character outlines (avg 20-40) - Add Stage B: connected-component analysis that finds small (<=64px), low-saturation opaque islands disconnected from the main character and clears them — these are enclosed background remnants that flood-fill cannot reach Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
Autofix Details
Bugbot Autofix prepared a fix for the issue found in the latest run.
- ✅ Fixed: Happy GIF always overwritten during single-expression regeneration
- I made happy.gif generation conditional during targeted expression/meme regeneration and allowed meme-only runs to proceed without requiring any expression input.
Or push these changes by commenting:
@cursor push efb373116a
Preview (efb373116a)
diff --git a/avatar-pack/scripts/process_avatar.py b/avatar-pack/scripts/process_avatar.py
--- a/avatar-pack/scripts/process_avatar.py
+++ b/avatar-pack/scripts/process_avatar.py
@@ -1203,12 +1203,17 @@
return
# Process expression images — skip any not provided (supports single-expression regen)
+ has_targeted_regen_input = any((
+ args.sad, args.angry, args.thinking,
+ args.meme_confused, args.meme_annoyed, args.meme_cracked,
+ ))
images = {
- 'happy': args.base,
'sad': args.sad,
'angry': args.angry,
'thinking': args.thinking,
}
+ if not is_expression_only or not has_targeted_regen_input:
+ images['happy'] = args.base
available = {}
for emotion, path in images.items():
@@ -1217,7 +1222,8 @@
elif path:
print(f'Warning: {emotion} image not found: {path}, skipping', file=sys.stderr)
- if not available:
+ has_meme_inputs = any((args.meme_confused, args.meme_annoyed, args.meme_cracked))
+ if not available and not has_meme_inputs:
print('Error: no expression images found', file=sys.stderr)
sys.exit(1)This Bugbot Autofix run was free. To enable autofix for future PRs, go to the Cursor dashboard.
…n regen Add --regen-happy flag so happy.gif is only regenerated when explicitly requested. During expression-only regen (scenario C option 3), the old code unconditionally mapped happy to args.base (128px), overwriting the 1K-sourced happy.gif with a degraded version. Now: full generation (Phase 6) passes --regen-happy, single-expression regen does not. Also allow meme-only invocations without expression inputs. Fixes: #20 (comment) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
Fixed in e1f528d. Added Resolves #20 (comment) |
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
Fixed in d4bdb4b — removed unused Resolves #20 (comment) |
…r pre-processed original base_image_original.png is already background-removed by save_base_image. Calling remove_background again enters the cleanup branch which can cumulatively erode light/neutral character features (white fur, gray accessories). Keep remove_background only for the else fallback where the input may not be pre-processed. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
Fixed in 356f2cc — Resolves #20 (comment) |
Rename skill directory and update all references across SKILL.md, GENERATE.md, process_avatar.py, README.md, README.zh.md, and CHANGELOG.md. No logic changes. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ransparency holes Pillow's ImageDraw replaces pixel values rather than compositing, so drawing outline diamonds at alpha=77 onto the opaque white card punched semi-transparent holes visible on dark backgrounds. Premultiply the outline color against white so the visual appearance is identical on white but fully opaque everywhere. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
Fixed in ac21693 — premultiply diamond outline color against white background so it stays fully opaque ( Resolves #20 (comment) |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit ac21693. Configure here.
|
Won't fix — the 24px clipping occurs only at the apex frame (1 of 8, 100ms) at @2x resolution. At 128px display size it's 12px, imperceptible during animation playback. Reducing stretch to eliminate it would weaken the bounce expressiveness for no visible gain. Resolves #20 (comment) |
The lightning crack in the cracked meme used the full character bbox center as its x-axis origin. For asymmetric distressed poses (slumped shoulders, arms to one side), this placed the crack off-center from the head. Now compute the centroid of opaque pixels in the upper 1/3 of the character (head region) for accurate centering. Text position and brightness sampling also benefit from the corrected face_cx. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>


Summary
base_image_original.pngguard so profile card matches new style after scenario C option 2; use local processed path for profile card generation__pycache__/to .gitignore, fix potentialUnboundLocalErrorin rembg cleanupTest plan
🤖 Generated with Claude Code
Note
Medium Risk
Adds a new skill plus a large image-processing pipeline (background removal, GIF/sticker generation) that could fail on edge-case inputs or missing system deps, but is isolated to the new
cola-avatar-pack/tooling.Overview
Introduces a new
cola-avatar-packskill that generates a pixel-art self-portrait, a profile card, 4 animated emoji GIFs, and 3 meme stickers, with a documented multi-phase flow for first-time generation and regeneration.Adds
cola-avatar-pack/scripts/process_avatar.pyto handle background removal (including optionalrembgCLI fallback and artifact cleanup), canvas fitting, animation frame generation, profile-card rendering (wuxing colors + rarity diamonds), and dual-size (128px+@2x) outputs for both GIFs and PNG stickers.Updates docs/changelog to surface the new skill in
README.md,README.zh.md, andCHANGELOG.md, and extends.gitignorefor Python cache/artifacts.Reviewed by Cursor Bugbot for commit a9d7f70. Bugbot is set up for automated code reviews on this repo. Configure here.