水印相机前端
This commit is contained in:
@@ -0,0 +1,79 @@
|
||||
import 'dart:io';
|
||||
import 'dart:ui' as ui;
|
||||
|
||||
import 'package:flutter/services.dart' show rootBundle;
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:image/image.dart' as img;
|
||||
|
||||
import 'package:qiangbao_accounting/models/watermark.dart';
|
||||
import 'package:qiangbao_accounting/pages/watermark/watermark_painter.dart';
|
||||
|
||||
/// 把水印渲染到一张模拟背景上并**写出图片文件**,用来用眼睛验收排版。
|
||||
///
|
||||
/// 为什么需要它:单元测试只能断言「不报错、尺寸对」,断言不了「好不好看」。
|
||||
/// 之前正是靠看图才发现「时间:2026.09.28 14:30」是 19 个字、被折行阈值切成
|
||||
/// 两行、最后一个「0」孤零零占了一行。
|
||||
///
|
||||
/// 跑法:
|
||||
/// ```
|
||||
/// flutter test test/watermark_preview_test.dart
|
||||
/// ```
|
||||
/// 输出图片的路径会打印在结果里,直接用图片查看器打开即可。
|
||||
///
|
||||
/// 注意:测试环境没有中文字体,汉字会渲染成方块(Ahem 测试字体)——
|
||||
/// **这是正常的**,看的是排版/位置/颜色,不是字形。真机上才是真汉字。
|
||||
void main() {
|
||||
TestWidgetsFlutterBinding.ensureInitialized();
|
||||
|
||||
/// 造一张「有明有暗」的底图,用来检查白字在浅色区域会不会糊
|
||||
img.Image makeBackground(int w, int h) {
|
||||
final bg = img.Image(width: w, height: h);
|
||||
for (var y = 0; y < h; y++) {
|
||||
for (var x = 0; x < w; x++) {
|
||||
final t = x / w;
|
||||
var v = (215 - 150 * t).round(); // 左亮右暗
|
||||
if (y > h * 0.55 && y < h * 0.62) v = 235; // 一条浅色横带,模拟高光
|
||||
bg.setPixelRgb(x, y, v, (v * 0.96).round(), (v * 0.9).round());
|
||||
}
|
||||
}
|
||||
return bg;
|
||||
}
|
||||
|
||||
test('渲染一张水印预览图供人工核对', () async {
|
||||
final iconData = await rootBundle.load('assets/images/watermark_camera.png');
|
||||
final codec = await ui.instantiateImageCodec(iconData.buffer.asUint8List());
|
||||
final brandIcon = (await codec.getNextFrame()).image;
|
||||
|
||||
// 全项打开,把四种行和品牌角标都覆盖到
|
||||
final settings = WatermarkSettings.defaults.copyWith(
|
||||
showWeather: true,
|
||||
showRemark: true,
|
||||
);
|
||||
final data = WatermarkData(
|
||||
time: DateTime(2026, 9, 28, 14, 30),
|
||||
address: '云南省昆明市五华区莲花池正街某小区 3 栋',
|
||||
weather: '晴',
|
||||
temperature: '25℃',
|
||||
remark: '和宝一起吃的那家店',
|
||||
);
|
||||
|
||||
final jpg = await composeWatermarkedJpeg(
|
||||
originalBytes: img.encodePng(makeBackground(1080, 1440)),
|
||||
settings: settings,
|
||||
data: data,
|
||||
brandIcon: brandIcon,
|
||||
maxWidth: 1080,
|
||||
);
|
||||
|
||||
// 顺带当一次端到端冒烟:产物必须是能解回来的合法 JPEG
|
||||
final decoded = img.decodeJpg(jpg);
|
||||
expect(decoded, isNotNull);
|
||||
expect(decoded!.width, 1080);
|
||||
expect(decoded.height, 1440);
|
||||
|
||||
final out = File('${Directory.systemTemp.path}/wm_preview.jpg')
|
||||
..writeAsBytesSync(jpg);
|
||||
// ignore: avoid_print
|
||||
print('水印预览图已写出(人工核对用): ${out.path}');
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user