import 'dart:io'; import 'package:carddex_demo/native/phash_loader.dart'; import 'package:carddex_demo/services/hash_library.dart'; import 'package:carddex_demo/services/phash_matcher.dart'; import 'package:path/path.dart' as p; Future main(List args) async { String? imagePath; var topN = 5; String? libPath; for (var i = 0; i < args.length; i++) { final a = args[i]; if ((a == '--image' || a == '-i') && i + 1 < args.length) { imagePath = args[++i]; } else if (a == '--top' && i + 1 < args.length) { topN = int.parse(args[++i]); } else if (a == '--lib' && i + 1 < args.length) { libPath = args[++i]; } else if (!a.startsWith('-') && imagePath == null) { imagePath = a; } } if (imagePath == null) { stderr.writeln( 'Usage: dart run tool/match.dart --image path/to.jpg [--top 5]', ); exit(1); } final root = Directory.current.path; libPath ??= _defaultLib(root); final hashesPath = p.join(root, 'data', 'hashes.json'); if (!File(hashesPath).existsSync()) { stderr.writeln('Missing $hashesPath — run: dart run tool/hashgen.dart'); exit(1); } final native = PhashNative(hostLibraryPath: libPath); final matcher = PhashMatcher(native: native); final library = await HashLibrary.loadFile(hashesPath); final bytes = await File(imagePath).readAsBytes(); final query = native.hashFromBytes(bytes); final matches = matcher.topN(query, library, n: topN); stdout.writeln('query: $imagePath'); stdout.writeln('hash: $query'); stdout.writeln('library: ${library.items.length} cards'); stdout.writeln('---'); for (var i = 0; i < matches.length; i++) { final m = matches[i]; final flag = m.confident ? 'confident' : 'low'; stdout.writeln( '#${i + 1} ${m.cardId} dist=${m.distance} score=${m.score} ($flag)', ); } } String _defaultLib(String root) { final dylib = p.join(root, 'native', 'phash', 'build', 'libphash.dylib'); final so = p.join(root, 'native', 'phash', 'build', 'libphash.so'); if (File(dylib).existsSync()) return dylib; if (File(so).existsSync()) return so; stderr.writeln('libphash not found under native/phash/build/'); exit(1); }