mirror of
https://github.com/zarzet/SpotiFLAC-Mobile.git
synced 2026-09-30 13:19:44 +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 parent
6038ce5777
commit
5053ed93ee
2 files changed
+47
-3
No files matched your search
@@ -1,9 +1,35 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
import 'dart:typed_data';
|
||||||
import 'dart:ui' as ui;
|
import 'dart:ui' as ui;
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/rendering.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.
|
/// 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.
|
/// Read back only 48 pixels across, at most three times a second when visible.
|
||||||
class MornyeArtworkContrast extends StatefulWidget {
|
class MornyeArtworkContrast extends StatefulWidget {
|
||||||
@@ -95,12 +121,11 @@ class _MornyeArtworkContrastState extends State<MornyeArtworkContrast> {
|
|||||||
for (var y = top; y < bottom; y++) {
|
for (var y = top; y < bottom; y++) {
|
||||||
for (var x = left; x < right; x++) {
|
for (var x = left; x < right; x++) {
|
||||||
final index = (y * image.width + x) * 4;
|
final index = (y * image.width + x) * 4;
|
||||||
luminance += Color.fromARGB(
|
luminance += artworkPixelLuminance(
|
||||||
255,
|
|
||||||
pixels.getUint8(index),
|
pixels.getUint8(index),
|
||||||
pixels.getUint8(index + 1),
|
pixels.getUint8(index + 1),
|
||||||
pixels.getUint8(index + 2),
|
pixels.getUint8(index + 2),
|
||||||
).computeLuminance();
|
);
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,25 @@ import 'package:flutter_test/flutter_test.dart';
|
|||||||
import 'package:spotiflac_android/widgets/mornye_artwork_contrast.dart';
|
import 'package:spotiflac_android/widgets/mornye_artwork_contrast.dart';
|
||||||
|
|
||||||
void main() {
|
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', (
|
testWidgets('foreground follows changing frames separately for each region', (
|
||||||
tester,
|
tester,
|
||||||
) async {
|
) async {
|
||||||
|
|||||||
Reference in new issue
Block a user