import 'dart:ui' as ui; import 'package:flutter/material.dart'; import 'package:aesthetica_wallpaper/models/recipe.dart'; // 壁纸预览绘制器 class WallpaperPreviewPainter extends CustomPainter { final ui.Image image; final Recipe recipe; WallpaperPreviewPainter({required this.image, required this.recipe}); // 构建颜色矩阵 ColorFilter _buildColorMatrix() { final double brightness = recipe.brightness; final double contrast = recipe.contrast; final double saturation = recipe.saturation; List matrix = [ 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, ]; // 应用饱和度 if (saturation != 1.0) { final sat = saturation; const lumR = 0.3086; const lumG = 0.6094; const lumB = 0.0820; matrix = [ lumR * (1 - sat) + sat, lumG * (1 - sat), lumB * (1 - sat), 0, 0, lumR * (1 - sat), lumG * (1 - sat) + sat, lumB * (1 - sat), 0, 0, lumR * (1 - sat), lumG * (1 - sat), lumB * (1 - sat) + sat, 0, 0, 0, 0, 0, 1, 0, ]; } // 应用对比度 if (contrast != 1.0) { final translate = (1.0 - contrast) * 128; matrix[0] *= contrast; matrix[5] *= contrast; matrix[10] *= contrast; matrix[4] += translate; matrix[9] += translate; matrix[14] += translate; } // 应用亮度 if (brightness != 0.0) { final b = brightness * 255; matrix[4] += b; matrix[9] += b; matrix[14] += b; } return ColorFilter.matrix(matrix); } @override void paint(Canvas canvas, Size size) { // 裁剪画布 canvas.clipRect(Offset.zero & size); // 准备画笔 final Paint paint = Paint()..filterQuality = FilterQuality.low; // 定义源矩形和目标矩形 final Rect srcRect = Rect.fromLTWH( 0, 0, image.width.toDouble(), image.height.toDouble(), ); final Rect dstRect = Rect.fromLTWH(0, 0, size.width, size.height); // 应用颜色矩阵 paint.colorFilter = _buildColorMatrix(); // 应用模糊 if (recipe.blur > 0.0) { paint.imageFilter = ui.ImageFilter.blur( sigmaX: recipe.blur, sigmaY: recipe.blur, ); } // 绘制图片 canvas.drawImageRect(image, srcRect, dstRect, paint); // 绘制文字叠加 if (recipe.overlayText.isNotEmpty) { final textPainter = TextPainter( text: TextSpan( text: recipe.overlayText, style: TextStyle( fontSize: 32, color: Color(recipe.textColor), fontWeight: FontWeight.bold, ), ), textDirection: ui.TextDirection.ltr, textAlign: TextAlign.center, ); textPainter.layout(maxWidth: size.width - 40); final offset = Offset( (size.width - textPainter.width) / 2, (size.height - textPainter.height) / 2, ); textPainter.paint(canvas, offset); } } @override bool shouldRepaint(covariant WallpaperPreviewPainter oldDelegate) { return oldDelegate.image != image || oldDelegate.recipe.brightness != recipe.brightness || oldDelegate.recipe.contrast != recipe.contrast || oldDelegate.recipe.saturation != recipe.saturation || oldDelegate.recipe.blur != recipe.blur || oldDelegate.recipe.overlayText != recipe.overlayText || oldDelegate.recipe.textColor != recipe.textColor; } }