mirror of
https://github.com/zarzet/SpotiFLAC-Mobile.git
synced 2026-09-29 12:52:13 +02:00
perf(mornye): reuse exact luminance contributions for contrast sampling
Use 6 KiB of lookup tables to avoid repeated Color allocations and exponentiation during frame sampling. Exhaustively verify exact Flutter luminance parity for every 8-bit RGB value.
This commit is contained in:
@@ -1,9 +1,35 @@
|
||||
import 'dart:async';
|
||||
import 'dart:typed_data';
|
||||
import 'dart:ui' as ui;
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/rendering.dart';
|
||||
|
||||
// Readback uses 8-bit sRGB. Cache each channel's exact Flutter luminance
|
||||
// contribution (6 KiB total), avoiding three powers and a Color per pixel.
|
||||
final _redLuminance = Float64List.fromList(
|
||||
List.generate(
|
||||
256,
|
||||
(value) => Color.fromARGB(255, value, 0, 0).computeLuminance(),
|
||||
),
|
||||
);
|
||||
final _greenLuminance = Float64List.fromList(
|
||||
List.generate(
|
||||
256,
|
||||
(value) => Color.fromARGB(255, 0, value, 0).computeLuminance(),
|
||||
),
|
||||
);
|
||||
final _blueLuminance = Float64List.fromList(
|
||||
List.generate(
|
||||
256,
|
||||
(value) => Color.fromARGB(255, 0, 0, value).computeLuminance(),
|
||||
),
|
||||
);
|
||||
|
||||
/// Matches [Color.computeLuminance] for an RGB pixel from an 8-bit readback.
|
||||
double artworkPixelLuminance(int red, int green, int blue) =>
|
||||
_redLuminance[red] + _greenLuminance[green] + _blueLuminance[blue];
|
||||
|
||||
/// Samples rendered video and its fade, rather than a static album palette.
|
||||
/// Read back only 48 pixels across, at most three times a second when visible.
|
||||
class MornyeArtworkContrast extends StatefulWidget {
|
||||
@@ -95,12 +121,11 @@ class _MornyeArtworkContrastState extends State<MornyeArtworkContrast> {
|
||||
for (var y = top; y < bottom; y++) {
|
||||
for (var x = left; x < right; x++) {
|
||||
final index = (y * image.width + x) * 4;
|
||||
luminance += Color.fromARGB(
|
||||
255,
|
||||
luminance += artworkPixelLuminance(
|
||||
pixels.getUint8(index),
|
||||
pixels.getUint8(index + 1),
|
||||
pixels.getUint8(index + 2),
|
||||
).computeLuminance();
|
||||
);
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,25 @@ import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:spotiflac_android/widgets/mornye_artwork_contrast.dart';
|
||||
|
||||
void main() {
|
||||
test('readback luminance matches Flutter exactly for every RGB pixel', () {
|
||||
for (var red = 0; red < 256; red++) {
|
||||
for (var green = 0; green < 256; green++) {
|
||||
for (var blue = 0; blue < 256; blue++) {
|
||||
final expected = Color.fromARGB(
|
||||
255,
|
||||
red,
|
||||
green,
|
||||
blue,
|
||||
).computeLuminance();
|
||||
final actual = artworkPixelLuminance(red, green, blue);
|
||||
if (actual != expected) {
|
||||
fail('RGB($red, $green, $blue): $actual != $expected');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
testWidgets('foreground follows changing frames separately for each region', (
|
||||
tester,
|
||||
) async {
|
||||
|
||||
Reference in New Issue
Block a user