From 560b0f07d1cf14e280089e065a8cd9d85d797ada Mon Sep 17 00:00:00 2001 From: John Thomas McDole Date: Sat, 14 Dec 2024 13:22:18 -0800 Subject: [PATCH] Unmultiply colors before brightening --- packages/flame/lib/src/extensions/image.dart | 42 +++++++++++++++----- 1 file changed, 31 insertions(+), 11 deletions(-) diff --git a/packages/flame/lib/src/extensions/image.dart b/packages/flame/lib/src/extensions/image.dart index 6dc0ce3a9b..b61b4a1935 100644 --- a/packages/flame/lib/src/extensions/image.dart +++ b/packages/flame/lib/src/extensions/image.dart @@ -78,17 +78,37 @@ extension ImageExtension on Image { final newPixelData = Uint8List(pixelData.length); for (var i = 0; i < pixelData.length; i += 4) { - final color = Color.fromARGB( - pixelData[i + 3], - pixelData[i + 0], - pixelData[i + 1], - pixelData[i + 2], - ).brighten(amount); - - newPixelData[i] = (color.r * 255).round(); - newPixelData[i + 1] = (color.g * 255).round(); - newPixelData[i + 2] = (color.b * 255).round(); - newPixelData[i + 3] = (color.a * 255).round(); + final a = pixelData[i + 3] / 255; + + // Lets avoid division by zero. + if (a == 0) { + newPixelData[i + 0] = pixelData[i + 0]; + newPixelData[i + 1] = pixelData[i + 1]; + newPixelData[i + 2] = pixelData[i + 2]; + newPixelData[i + 3] = pixelData[i + 3]; + continue; + } + + // Unmultiply the color + var r = (pixelData[i + 0] / 255) / a; + var g = (pixelData[i + 1] / 255) / a; + var b = (pixelData[i + 2] / 255) / a; + + // Brighten in a color accurate way + r = r + (1.0 - r) * amount; + g = g + (1.0 - g) * amount; + b = b + (1.0 - b) * amount; + + // Clamp + r = r.clamp(0, 1.0); + g = g.clamp(0, 1.0); + b = b.clamp(0, 1.0); + + // Pre-multiply the new color. + newPixelData[i + 0] = (r * a * 255).round(); + newPixelData[i + 1] = (g * a * 255).round(); + newPixelData[i + 2] = (b * a * 255).round(); + newPixelData[i + 3] = pixelData[i + 3]; } return fromPixels(newPixelData, width, height); }