mirror of
https://github.com/Solido/mixbox.git
synced 2026-03-19 14:39:34 +01:00
init
This commit is contained in:
422
lib/mixbox.dart
Normal file
422
lib/mixbox.dart
Normal file
@@ -0,0 +1,422 @@
|
||||
import 'dart:typed_data';
|
||||
import 'dart:math' as math;
|
||||
|
||||
/// MIXBOX 2.0 - Mélange de couleurs physiquement réaliste
|
||||
/// (c) 2022 Secret Weapons. Tous droits réservés.
|
||||
/// License: Creative Commons Attribution-NonCommercial 4.0
|
||||
/// Auteurs: Sarka Sochorova et Ondrej Jamriska
|
||||
///
|
||||
/// USAGE BASIQUE:
|
||||
/// int colorMix = Mixbox.lerp(color1, color2, 0.5);
|
||||
///
|
||||
/// MÉLANGE MULTI-COULEURS:
|
||||
/// var z1 = Mixbox.rgbToLatent(color1);
|
||||
/// var z2 = Mixbox.rgbToLatent(color2);
|
||||
/// var z3 = Mixbox.rgbToLatent(color3);
|
||||
///
|
||||
/// var zMix = List.generate(Mixbox.latentSize, (i) =>
|
||||
/// 0.3 * z1[i] + 0.6 * z2[i] + 0.1 * z3[i]
|
||||
/// );
|
||||
///
|
||||
/// int colorMix = Mixbox.latentToRgb(zMix);
|
||||
///
|
||||
/// COULEURS PIGMENTS:
|
||||
/// Cadmium Yellow: (254, 236, 0)
|
||||
/// Hansa Yellow: (252, 211, 0)
|
||||
/// Cadmium Orange: (255, 105, 0)
|
||||
/// Cadmium Red: (255, 39, 2)
|
||||
/// Quinacridone Magenta: (128, 2, 46)
|
||||
/// Cobalt Violet: (78, 0, 66)
|
||||
/// Ultramarine Blue: (25, 0, 89)
|
||||
/// Cobalt Blue: (0, 33, 133)
|
||||
/// Phthalo Blue: (13, 27, 68)
|
||||
/// Phthalo Green: (0, 60, 50)
|
||||
/// Permanent Green: (7, 109, 22)
|
||||
/// Sap Green: (107, 148, 4)
|
||||
/// Burnt Sienna: (123, 72, 0)
|
||||
class Mixbox {
|
||||
static const int latentSize = 7;
|
||||
static late Uint8List _lut;
|
||||
static bool _initialized = false;
|
||||
static bool get isInitialized => _initialized;
|
||||
|
||||
/// Initialise la LUT
|
||||
/// Appelez cette méthode une fois au démarrage de l'app
|
||||
static void initialize(Uint8List lutData) {
|
||||
if (_initialized) return;
|
||||
|
||||
_lut = lutData;
|
||||
_initialized = true;
|
||||
}
|
||||
|
||||
/// Charge la LUT depuis un fichier asset
|
||||
/// Exemple: await Mixbox.initializeFromAsset('assets/mixbox_lut.dat');
|
||||
static Future<void> initializeFromAsset(String assetPath) async {
|
||||
// À implémenter selon votre loader d'assets Flutter
|
||||
// import 'package:flutter/services.dart';
|
||||
// final data = await rootBundle.load(assetPath);
|
||||
// initialize(data.buffer.asUint8List());
|
||||
}
|
||||
|
||||
/// Mélange linéaire entre deux couleurs (format int ARGB 32-bit)
|
||||
///
|
||||
/// [color1] et [color2]: Couleurs au format 0xAARRGGBB
|
||||
/// [t]: Facteur de mélange [0.0-1.0], 0.0 = color1, 1.0 = color2
|
||||
///
|
||||
/// Retourne: Couleur mélangée au format 0xAARRGGBB
|
||||
static int lerp(int color1, int color2, double t) {
|
||||
final latent1 = rgbToLatent(color1);
|
||||
final latent2 = rgbToLatent(color2);
|
||||
|
||||
final latentMix = List<double>.generate(latentSize, (i) => (1.0 - t) * latent1[i] + t * latent2[i]);
|
||||
|
||||
final alpha1 = (color1 >> 24) & 0xFF;
|
||||
final alpha2 = (color2 >> 24) & 0xFF;
|
||||
final alphaMix = _clamp0255(((1.0 - t) * alpha1 + t * alpha2).round());
|
||||
|
||||
return (alphaMix << 24) | (latentToRgb(latentMix) & 0xFFFFFF);
|
||||
}
|
||||
|
||||
/// Mélange entre deux couleurs au format liste [r, g, b] ou [r, g, b, a]
|
||||
///
|
||||
/// Valeurs: 0-255 pour chaque composante
|
||||
static List<int> lerpList(List<int> color1, List<int> color2, double t) {
|
||||
final latent1 = rgbToLatentFromList(color1);
|
||||
final latent2 = rgbToLatentFromList(color2);
|
||||
|
||||
final latentMix = List<double>.generate(latentSize, (i) => (1.0 - t) * latent1[i] + t * latent2[i]);
|
||||
|
||||
final colorMix = latentToRgb(latentMix);
|
||||
|
||||
if (color1.length == 3 && color2.length == 3) {
|
||||
return [(colorMix >> 16) & 0xFF, (colorMix >> 8) & 0xFF, colorMix & 0xFF];
|
||||
}
|
||||
|
||||
final alpha1 = color1.length > 3 ? color1[3] : 255;
|
||||
final alpha2 = color2.length > 3 ? color2[3] : 255;
|
||||
final alphaMix = _clamp0255(((1.0 - t) * alpha1 + t * alpha2).round());
|
||||
|
||||
return [(colorMix >> 16) & 0xFF, (colorMix >> 8) & 0xFF, colorMix & 0xFF, alphaMix];
|
||||
}
|
||||
|
||||
/// Mélange entre deux couleurs au format float [0.0-1.0]
|
||||
///
|
||||
/// Format: [r, g, b] ou [r, g, b, a] avec valeurs 0.0-1.0
|
||||
static List<double> lerpFloat(List<double> color1, List<double> color2, double t) {
|
||||
final latent1 = floatRgbToLatent(color1[0], color1[1], color1[2]);
|
||||
final latent2 = floatRgbToLatent(color2[0], color2[1], color2[2]);
|
||||
|
||||
final latentMix = List<double>.generate(latentSize, (i) => (1.0 - t) * latent1[i] + t * latent2[i]);
|
||||
|
||||
final colorMix = latentToFloatRgb(latentMix);
|
||||
|
||||
if (color1.length == 3 && color2.length == 3) {
|
||||
return colorMix;
|
||||
}
|
||||
|
||||
final alpha1 = color1.length > 3 ? color1[3] : 1.0;
|
||||
final alpha2 = color2.length > 3 ? color2[3] : 1.0;
|
||||
final alphaMix = (1.0 - t) * alpha1 + t * alpha2;
|
||||
|
||||
return [colorMix[0], colorMix[1], colorMix[2], alphaMix];
|
||||
}
|
||||
|
||||
/// Mélange entre deux couleurs RGB linéaires [0.0-1.0]
|
||||
///
|
||||
/// Pour couleurs en espace linéaire (non-sRGB)
|
||||
static List<double> lerpLinearFloat(List<double> color1, List<double> color2, double t) {
|
||||
final latent1 = linearFloatRgbToLatent(color1[0], color1[1], color1[2]);
|
||||
final latent2 = linearFloatRgbToLatent(color2[0], color2[1], color2[2]);
|
||||
|
||||
final latentMix = List<double>.generate(latentSize, (i) => (1.0 - t) * latent1[i] + t * latent2[i]);
|
||||
|
||||
final colorMix = latentToLinearFloatRgb(latentMix);
|
||||
|
||||
if (color1.length == 3 && color2.length == 3) {
|
||||
return colorMix;
|
||||
}
|
||||
|
||||
final alpha1 = color1.length > 3 ? color1[3] : 1.0;
|
||||
final alpha2 = color2.length > 3 ? color2[3] : 1.0;
|
||||
final alphaMix = (1.0 - t) * alpha1 + t * alpha2;
|
||||
|
||||
return [colorMix[0], colorMix[1], colorMix[2], alphaMix];
|
||||
}
|
||||
|
||||
/// Conversion RGB (0-255) → espace latent
|
||||
static List<double> rgbToLatentFromInts(int r, int g, int b) {
|
||||
return floatRgbToLatent(r / 255.0, g / 255.0, b / 255.0);
|
||||
}
|
||||
|
||||
/// Conversion RGB liste → espace latent
|
||||
static List<double> rgbToLatentFromList(List<int> rgb) {
|
||||
return rgbToLatentFromInts(rgb[0], rgb[1], rgb[2]);
|
||||
}
|
||||
|
||||
/// Conversion RGB int (0xAARRGGBB) → espace latent
|
||||
static List<double> rgbToLatent(int color) {
|
||||
return rgbToLatentFromInts((color >> 16) & 0xFF, (color >> 8) & 0xFF, color & 0xFF);
|
||||
}
|
||||
|
||||
/// Conversion espace latent → RGB int (0xAARRGGBB)
|
||||
static int latentToRgb(List<double> latent) {
|
||||
final rgb = _evalPolynomial(latent[0], latent[1], latent[2], latent[3]);
|
||||
return 0xFF000000 |
|
||||
((_clamp01(rgb[0] + latent[4]) * 255.0).round() << 16) |
|
||||
((_clamp01(rgb[1] + latent[5]) * 255.0).round() << 8) |
|
||||
((_clamp01(rgb[2] + latent[6]) * 255.0).round());
|
||||
}
|
||||
|
||||
/// Conversion RGB float (0.0-1.0) → espace latent
|
||||
///
|
||||
/// C'est le cœur de l'algorithme Mixbox
|
||||
static List<double> floatRgbToLatent(double r, double g, double b) {
|
||||
r = _clamp01(r);
|
||||
g = _clamp01(g);
|
||||
b = _clamp01(b);
|
||||
|
||||
// Interpolation trilinéaire dans la LUT 64x64x64
|
||||
final x = r * 63.0;
|
||||
final y = g * 63.0;
|
||||
final z = b * 63.0;
|
||||
|
||||
final ix = x.floor();
|
||||
final iy = y.floor();
|
||||
final iz = z.floor();
|
||||
|
||||
final tx = x - ix;
|
||||
final ty = y - iy;
|
||||
final tz = z - iz;
|
||||
|
||||
final xyz = (ix + iy * 64 + iz * 64 * 64) & 0x3FFFF;
|
||||
|
||||
double c0 = 0.0;
|
||||
double c1 = 0.0;
|
||||
double c2 = 0.0;
|
||||
|
||||
// Interpolation aux 8 sommets du cube
|
||||
double w;
|
||||
|
||||
w = (1.0 - tx) * (1.0 - ty) * (1.0 - tz);
|
||||
c0 += w * (_lut[xyz + 192] & 0xFF);
|
||||
c1 += w * (_lut[xyz + 262336] & 0xFF);
|
||||
c2 += w * (_lut[xyz + 524480] & 0xFF);
|
||||
|
||||
w = tx * (1.0 - ty) * (1.0 - tz);
|
||||
c0 += w * (_lut[xyz + 193] & 0xFF);
|
||||
c1 += w * (_lut[xyz + 262337] & 0xFF);
|
||||
c2 += w * (_lut[xyz + 524481] & 0xFF);
|
||||
|
||||
w = (1.0 - tx) * ty * (1.0 - tz);
|
||||
c0 += w * (_lut[xyz + 256] & 0xFF);
|
||||
c1 += w * (_lut[xyz + 262400] & 0xFF);
|
||||
c2 += w * (_lut[xyz + 524544] & 0xFF);
|
||||
|
||||
w = tx * ty * (1.0 - tz);
|
||||
c0 += w * (_lut[xyz + 257] & 0xFF);
|
||||
c1 += w * (_lut[xyz + 262401] & 0xFF);
|
||||
c2 += w * (_lut[xyz + 524545] & 0xFF);
|
||||
|
||||
w = (1.0 - tx) * (1.0 - ty) * tz;
|
||||
c0 += w * (_lut[xyz + 4288] & 0xFF);
|
||||
c1 += w * (_lut[xyz + 266432] & 0xFF);
|
||||
c2 += w * (_lut[xyz + 528576] & 0xFF);
|
||||
|
||||
w = tx * (1.0 - ty) * tz;
|
||||
c0 += w * (_lut[xyz + 4289] & 0xFF);
|
||||
c1 += w * (_lut[xyz + 266433] & 0xFF);
|
||||
c2 += w * (_lut[xyz + 528577] & 0xFF);
|
||||
|
||||
w = (1.0 - tx) * ty * tz;
|
||||
c0 += w * (_lut[xyz + 4352] & 0xFF);
|
||||
c1 += w * (_lut[xyz + 266496] & 0xFF);
|
||||
c2 += w * (_lut[xyz + 528640] & 0xFF);
|
||||
|
||||
w = tx * ty * tz;
|
||||
c0 += w * (_lut[xyz + 4353] & 0xFF);
|
||||
c1 += w * (_lut[xyz + 266497] & 0xFF);
|
||||
c2 += w * (_lut[xyz + 528641] & 0xFF);
|
||||
|
||||
c0 /= 255.0;
|
||||
c1 /= 255.0;
|
||||
c2 /= 255.0;
|
||||
|
||||
final c3 = 1.0 - (c0 + c1 + c2);
|
||||
|
||||
// Calcul du résidu via polynôme
|
||||
final rgb = _evalPolynomial(c0, c1, c2, c3);
|
||||
|
||||
return [c0, c1, c2, c3, r - rgb[0], g - rgb[1], b - rgb[2]];
|
||||
}
|
||||
|
||||
/// Conversion RGB float liste → espace latent
|
||||
static List<double> floatRgbToLatentFromList(List<double> rgb) {
|
||||
return floatRgbToLatent(rgb[0], rgb[1], rgb[2]);
|
||||
}
|
||||
|
||||
/// Conversion espace latent → RGB float (0.0-1.0)
|
||||
static List<double> latentToFloatRgb(List<double> latent) {
|
||||
final rgb = _evalPolynomial(latent[0], latent[1], latent[2], latent[3]);
|
||||
return [_clamp01(rgb[0] + latent[4]), _clamp01(rgb[1] + latent[5]), _clamp01(rgb[2] + latent[6])];
|
||||
}
|
||||
|
||||
/// Conversion RGB linéaire → espace latent
|
||||
static List<double> linearFloatRgbToLatent(double r, double g, double b) {
|
||||
return floatRgbToLatent(_linearToSrgb(r), _linearToSrgb(g), _linearToSrgb(b));
|
||||
}
|
||||
|
||||
/// Conversion RGB linéaire liste → espace latent
|
||||
static List<double> linearFloatRgbToLatentFromList(List<double> rgb) {
|
||||
return linearFloatRgbToLatent(rgb[0], rgb[1], rgb[2]);
|
||||
}
|
||||
|
||||
/// Conversion espace latent → RGB linéaire
|
||||
static List<double> latentToLinearFloatRgb(List<double> latent) {
|
||||
final rgb = latentToFloatRgb(latent);
|
||||
return [_srgbToLinear(rgb[0]), _srgbToLinear(rgb[1]), _srgbToLinear(rgb[2])];
|
||||
}
|
||||
|
||||
/// Évaluation du polynôme avec coefficients optimisés
|
||||
///
|
||||
/// Représente le mélange physique des pigments
|
||||
static List<double> _evalPolynomial(double c0, double c1, double c2, double c3) {
|
||||
double r = 0.0;
|
||||
double g = 0.0;
|
||||
double b = 0.0;
|
||||
|
||||
// Pré-calcul des termes
|
||||
final c00 = c0 * c0;
|
||||
final c11 = c1 * c1;
|
||||
final c22 = c2 * c2;
|
||||
final c33 = c3 * c3;
|
||||
final c01 = c0 * c1;
|
||||
final c02 = c0 * c2;
|
||||
final c12 = c1 * c2;
|
||||
|
||||
double w;
|
||||
|
||||
// Termes cubiques purs
|
||||
w = c0 * c00;
|
||||
r += 0.07717053 * w;
|
||||
g += 0.02826978 * w;
|
||||
b += 0.24832992 * w;
|
||||
|
||||
w = c1 * c11;
|
||||
r += 0.95912302 * w;
|
||||
g += 0.80256528 * w;
|
||||
b += 0.03561839 * w;
|
||||
|
||||
w = c2 * c22;
|
||||
r += 0.74683774 * w;
|
||||
g += 0.04868586 * w;
|
||||
b += 0.00000000 * w;
|
||||
|
||||
w = c3 * c33;
|
||||
r += 0.99518138 * w;
|
||||
g += 0.99978149 * w;
|
||||
b += 0.99704802 * w;
|
||||
|
||||
// Termes quadratiques-linéaires (c0)
|
||||
w = c00 * c1;
|
||||
r += 0.04819146 * w;
|
||||
g += 0.83363781 * w;
|
||||
b += 0.32515377 * w;
|
||||
|
||||
w = c01 * c1;
|
||||
r += -0.68146950 * w;
|
||||
g += 1.46107803 * w;
|
||||
b += 1.06980936 * w;
|
||||
|
||||
w = c00 * c2;
|
||||
r += 0.27058419 * w;
|
||||
g += -0.15324870 * w;
|
||||
b += 1.98735057 * w;
|
||||
|
||||
w = c02 * c2;
|
||||
r += 0.80478189 * w;
|
||||
g += 0.67093710 * w;
|
||||
b += 0.18424500 * w;
|
||||
|
||||
w = c00 * c3;
|
||||
r += -0.35031003 * w;
|
||||
g += 1.37855826 * w;
|
||||
b += 3.68865000 * w;
|
||||
|
||||
w = c0 * c33;
|
||||
r += 1.05128046 * w;
|
||||
g += 1.97815239 * w;
|
||||
b += 2.82989073 * w;
|
||||
|
||||
// Termes quadratiques-linéaires (c1)
|
||||
w = c11 * c2;
|
||||
r += 3.21607125 * w;
|
||||
g += 0.81270228 * w;
|
||||
b += 1.03384539 * w;
|
||||
|
||||
w = c1 * c22;
|
||||
r += 2.78893374 * w;
|
||||
g += 0.41565549 * w;
|
||||
b += -0.04487295 * w;
|
||||
|
||||
w = c11 * c3;
|
||||
r += 3.02162577 * w;
|
||||
g += 2.55374103 * w;
|
||||
b += 0.32766114 * w;
|
||||
|
||||
w = c1 * c33;
|
||||
r += 2.95124691 * w;
|
||||
g += 2.81201112 * w;
|
||||
b += 1.17578442 * w;
|
||||
|
||||
// Termes quadratiques-linéaires (c2)
|
||||
w = c22 * c3;
|
||||
r += 2.82677043 * w;
|
||||
g += 0.79933038 * w;
|
||||
b += 1.81715262 * w;
|
||||
|
||||
w = c2 * c33;
|
||||
r += 2.99691099 * w;
|
||||
g += 1.22593053 * w;
|
||||
b += 1.80653661 * w;
|
||||
|
||||
// Termes linéaires mixtes
|
||||
w = c01 * c2;
|
||||
r += 1.87394106 * w;
|
||||
g += 2.05027182 * w;
|
||||
b += -0.29835996 * w;
|
||||
|
||||
w = c01 * c3;
|
||||
r += 2.56609566 * w;
|
||||
g += 7.03428198 * w;
|
||||
b += 0.62575374 * w;
|
||||
|
||||
w = c02 * c3;
|
||||
r += 4.08329484 * w;
|
||||
g += -1.40408358 * w;
|
||||
b += 2.14995522 * w;
|
||||
|
||||
w = c12 * c3;
|
||||
r += 6.00078678 * w;
|
||||
g += 2.55552042 * w;
|
||||
b += 1.90739502 * w;
|
||||
|
||||
return [r, g, b];
|
||||
}
|
||||
|
||||
// Utilitaires
|
||||
static double _clamp01(double x) {
|
||||
return x < 0.0 ? 0.0 : (x > 1.0 ? 1.0 : x);
|
||||
}
|
||||
|
||||
static int _clamp0255(int x) {
|
||||
return x < 0 ? 0 : (x > 255 ? 255 : x);
|
||||
}
|
||||
|
||||
static double _srgbToLinear(double x) {
|
||||
return (x >= 0.04045) ? math.pow((x + 0.055) / 1.055, 2.4).toDouble() : x / 12.92;
|
||||
}
|
||||
|
||||
static double _linearToSrgb(double x) {
|
||||
return (x >= 0.0031308) ? 1.055 * math.pow(x, 1.0 / 2.4).toDouble() - 0.055 : 12.92 * x;
|
||||
}
|
||||
}
|
||||
114
lib/mixbox_loader.dart
Normal file
114
lib/mixbox_loader.dart
Normal file
@@ -0,0 +1,114 @@
|
||||
import 'dart:typed_data';
|
||||
import 'dart:ui';
|
||||
import 'package:flutter/services.dart' show rootBundle;
|
||||
import 'package:archive/archive.dart';
|
||||
import 'package:mixbox/mixbox.dart'; // pub.dev/packages/archive
|
||||
|
||||
/// Helper pour initialiser Mixbox avec la LUT depuis les assets
|
||||
class MixboxLoader {
|
||||
/// Charge et initialise la LUT depuis un fichier asset
|
||||
///
|
||||
/// Le fichier mixbox_lut.dat doit être placé dans assets/
|
||||
/// et déclaré dans pubspec.yaml:
|
||||
///
|
||||
/// flutter:
|
||||
/// assets:
|
||||
/// - assets/mixbox_lut.dat
|
||||
///
|
||||
/// Usage:
|
||||
/// await MixboxLoader.initializeFromAsset('assets/mixbox_lut.dat');
|
||||
static Future<void> initializeFromAsset(String assetPath) async {
|
||||
final data = await rootBundle.load(assetPath);
|
||||
final bytes = data.buffer.asUint8List();
|
||||
|
||||
// Décompression (le fichier original utilise Deflate)
|
||||
final decompressed = _decompressLutData(bytes);
|
||||
|
||||
// Note: La méthode initialize() doit être adaptée dans mixbox.dart
|
||||
// pour accepter les données décompressées
|
||||
Mixbox.initialize(decompressed);
|
||||
}
|
||||
|
||||
/// Décompresse les données de la LUT
|
||||
static Uint8List _decompressLutData(Uint8List compressedData) {
|
||||
// Skip les 192 premiers bytes (header)
|
||||
final deflatedBytes = compressedData.sublist(192);
|
||||
|
||||
// Décompression avec raw deflate
|
||||
final inflated = Inflate(deflatedBytes).getBytes();
|
||||
|
||||
// Post-traitement: reconstruction différentielle
|
||||
for (int i = 0; i < inflated.length; i++) {
|
||||
final previous = ((i & 63) != 0) ? inflated[i - 1] : 127;
|
||||
inflated[i] = (previous + (inflated[i] - 127)) & 0xFF;
|
||||
}
|
||||
|
||||
// Création du buffer final avec padding pour l'interpolation
|
||||
// Taille: (64^3 * 3) + 4353 = 790785
|
||||
final lut = Uint8List(64 * 64 * 64 * 3 + 4353);
|
||||
lut.setAll(0, inflated);
|
||||
|
||||
return lut;
|
||||
}
|
||||
|
||||
/// Génère une LUT de test (approximation simple, non-production!)
|
||||
/// Utilisez ceci uniquement pour les tests sans le fichier .dat
|
||||
static Uint8List generateTestLut() {
|
||||
final size = 64 * 64 * 64 * 3 + 4353;
|
||||
final lut = Uint8List(size);
|
||||
|
||||
// Approximation linéaire simple (pas physiquement correct!)
|
||||
for (int r = 0; r < 64; r++) {
|
||||
for (int g = 0; g < 64; g++) {
|
||||
for (int b = 0; b < 64; b++) {
|
||||
final idx = r + g * 64 + b * 64 * 64;
|
||||
|
||||
// Valeurs approximatives (à ne PAS utiliser en production)
|
||||
lut[idx + 192] = (r * 4).clamp(0, 255);
|
||||
lut[idx + 262336] = (g * 4).clamp(0, 255);
|
||||
lut[idx + 524480] = (b * 4).clamp(0, 255);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return lut;
|
||||
}
|
||||
}
|
||||
|
||||
/// Extension pour faciliter l'utilisation avec Flutter Color
|
||||
extension MixboxColorExtension on Color {
|
||||
/// Convertit Flutter Color en format Mixbox (0xAARRGGBB)
|
||||
int toMixboxInt() {
|
||||
return (alpha << 24) | (red << 16) | (green << 8) | blue;
|
||||
}
|
||||
|
||||
/// Convertit Flutter Color en format Mixbox float [r, g, b, a]
|
||||
List<double> toMixboxFloat() {
|
||||
return [red / 255.0, green / 255.0, blue / 255.0, alpha / 255.0];
|
||||
}
|
||||
|
||||
/// Mélange cette couleur avec une autre via Mixbox
|
||||
Color mixWith(Color other, double t) {
|
||||
final mixed = Mixbox.lerp(toMixboxInt(), other.toMixboxInt(), t);
|
||||
return Color(mixed);
|
||||
}
|
||||
|
||||
/// Crée une Color depuis un int Mixbox
|
||||
static Color fromMixboxInt(int mixboxColor) {
|
||||
return Color(mixboxColor);
|
||||
}
|
||||
|
||||
/// Crée une Color depuis un float Mixbox [r, g, b] ou [r, g, b, a]
|
||||
static Color fromMixboxFloat(List<double> rgb) {
|
||||
final r = (rgb[0] * 255).round().clamp(0, 255);
|
||||
final g = (rgb[1] * 255).round().clamp(0, 255);
|
||||
final b = (rgb[2] * 255).round().clamp(0, 255);
|
||||
final a = rgb.length > 3 ? (rgb[3] * 255).round().clamp(0, 255) : 255;
|
||||
|
||||
return Color.fromARGB(a, r, g, b);
|
||||
}
|
||||
}
|
||||
|
||||
// Ajoutez cette dépendance dans pubspec.yaml:
|
||||
// dependencies:
|
||||
// archive: ^3.4.0
|
||||
Reference in New Issue
Block a user