Skip to content

apply_auto_shading inverts colors on indexed sprites #11

Description

@willibrandon

Bug Description

The apply_auto_shading tool inverts colors when working with indexed color sprites. For example, a tree sprite with brown trunk and green foliage ends up with green trunk and brown foliage after shading.

Root Cause

The bug occurs in the color mode conversion step in pkg/aseprite/lua_auto_shading.go lines 81-85:

-- Convert color mode if needed
if shadedImg.colorMode ~= spr.colorMode then
    finalImg = Image(shadedImg.width, shadedImg.height, spr.colorMode)
    -- Use SRC blend mode to properly convert colors
    finalImg:drawImage(shadedImg, Point(0, 0), 255, BlendMode.SRC)
end

Workflow that causes the bug:

  1. Export cel from indexed sprite to RGB PNG (auto_shading.go:90-124)
  2. Apply shading in Go, generate new RGB colors (auto_shading.go:144-153)
  3. Load shaded RGB image in Lua (lua_auto_shading.go:65-68)
  4. Convert RGB back to indexed using drawImage(BlendMode.SRC) (lua_auto_shading.go:81-85)

The problem: drawImage(BlendMode.SRC) performs nearest-color matching against the existing palette without preserving original pixel-to-index relationships.

Original indexed sprite:

  • Palette index 1 = Forest Green (#228B22) → used by foliage pixels
  • Palette index 2 = Brown (#844A14) → used by trunk pixels

After RGB shading and conversion back to indexed:

  • Shaded brown RGB happens to be closer to green palette entry → maps to green index
  • Shaded green RGB happens to be closer to brown palette entry → maps to brown index

Result: Colors swap - brown foliage, green trunk.

Steps to Reproduce

  1. Create indexed color sprite with distinct regions (e.g., tree with brown trunk, green foliage)
  2. Call apply_auto_shading with any light direction, intensity 0.5, style "smooth", hue_shift true
  3. Observe colors are inverted in the output

Expected Behavior

Shading should preserve the original color assignments:

  • Trunk stays brown (with shading gradients)
  • Foliage stays green (with shading gradients)

Actual Behavior

Colors get inverted:

  • Trunk becomes green (with shading gradients)
  • Foliage becomes brown (with shading gradients)

Suggested Fixes

Option A: Keep RGB mode during shading

  • Don't convert back to indexed mode
  • Let the sprite remain in RGB with full color depth
  • Simplest fix, but changes color mode

Option B: Build proper color mapping

  • Before shading, record which pixels use which palette indices
  • After shading, map new RGB values back to original indices
  • Preserves indexed mode and color relationships

Option C: Add colors to palette first

  • Add all new shaded colors to palette before applying shaded image
  • Create proper index mapping for new colors
  • Use the mapped indices when applying shaded pixels
  • Most complex but preserves indexed mode properly

Impact

This affects any indexed color sprite when using apply_auto_shading. RGB sprites are not affected.

Environment

  • pixel-mcp version: v0.5.0
  • Tested with Aseprite indexed color sprites
  • Reproduced on macOS (likely affects all platforms)

Additional Context

This was discovered during Test 13 of pixel-plugin testing checklist, where a tree sprite's trunk and foliage colors were inverted after applying auto-shading.

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions