import 'dart:typed_data'; import 'package:image/image.dart' as img; /// 按一次快照帧:单平面 BGRA/RGBA 像素(两平台分析帧均为竖屏单平面 4 通道)。 /// 即喂给 YOLO 推理的同一帧,尺寸与推理输入同源。 class FrameSnapshot { final Uint8List plane; final int bytesPerRow; final int width; final int height; /// true = BGRA 字节序(Android 原生通道默认 / iOS bgra8888),false = RGBA final bool bgra; const FrameSnapshot({ required this.plane, required this.bytesPerRow, required this.width, required this.height, required this.bgra, }); } /// 在 isolate 执行:整帧像素行拷贝 → 解码为 Image → jpg q85 重编码。 /// 与推理帧同源同尺寸、重编码天然剥离全部元数据(合规硬要求) Uint8List encodeFrameJpeg(FrameSnapshot snap) { final packed = Uint8List(snap.width * snap.height * 4); for (var y = 0; y < snap.height; y++) { final srcStart = y * snap.bytesPerRow; final dstStart = y * snap.width * 4; packed.setRange(dstStart, dstStart + snap.width * 4, snap.plane.sublist(srcStart, srcStart + snap.width * 4)); } final image = img.Image.fromBytes( width: snap.width, height: snap.height, bytes: packed.buffer, numChannels: 4, order: snap.bgra ? img.ChannelOrder.bgra : img.ChannelOrder.rgba, ); return Uint8List.fromList(img.encodeJpg(image, quality: 85)); } /// 单独同意弹窗结果存储 key(FlutterSecureStorage,与 terms_accepted 同库) const falseTargetConsentKey = 'false_target_consent';