import 'dart:ffi'; import 'dart:io'; import 'package:ffi/ffi.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/services.dart'; import 'package:path_provider/path_provider.dart'; import 'dynamic_lib_singleton.dart'; class DocCleanFilter { static final DynamicLibrary _nativeVision = DynamicLibSingleton().dl; // static final int Function(Pointer src, Pointer> dst, // int width, int height) _nativeAdd = // _nativeVision // .lookup< // NativeFunction< // Int32 Function(Pointer, Pointer>, Int32, // Int32)>>('native_add') // .asFunction(); static final int Function(Pointer modelPath) _nativeInit = _nativeVision .lookup)>>('init') .asFunction(); static final void Function(int docFilterPtr) _nativeRelease = _nativeVision .lookup>('release') .asFunction(); static final int Function( Pointer imgPath, Pointer dstImgPath, int docFilterAdr) _nativeProc = _nativeVision .lookup< NativeFunction< Int32 Function( Pointer, Pointer, IntPtr)>>('process') .asFunction(); static Future _getModelPath() async { const modelName = "ssim_0.85_psnr_22.12_model_4.tflite"; // const modelName = "ssim_0.87_psnr_23.88_model_50.tflite"; final tempDir = await getTemporaryDirectory(); final modelCachePath = "${tempDir.path}/$modelName"; final file = File(modelCachePath); final exists = await file.exists(); if (!exists) { final modelData = await rootBundle.load("packages/native_vision/assets/$modelName"); final buffer = modelData.buffer; final result = await file.writeAsBytes( buffer.asUint8List(modelData.offsetInBytes, modelData.lengthInBytes)); } return file.path; } static int _initDocModel(String modelPath) { final modelPathPtr = modelPath.toNativeUtf8(); final docfilterPtr = _nativeInit(modelPathPtr); malloc.free(modelPathPtr); return docfilterPtr; } static Future init() async { final modelPath = await _getModelPath(); final docfilterPtr = await compute(_initDocModel, modelPath); return docfilterPtr; } static String _processAsync(args) { String origImgPath = args["origImgPath"]; int docFilterPtr = args["docFilterPtr"]; final origImgPathPtr = origImgPath.toNativeUtf8(); final dstImgPath = "${File(origImgPath).parent.path}/processed_${DateTime.now().millisecondsSinceEpoch}.jpg"; final dstImgPathPtr = dstImgPath.toNativeUtf8(); final succ = _nativeProc(origImgPathPtr, dstImgPathPtr, docFilterPtr); malloc.free(origImgPathPtr); malloc.free(dstImgPathPtr); return succ == 1 ? dstImgPath : ""; } static Future process(String origImgPath, int docFilterPtr) async { Map args = {"docFilterPtr": docFilterPtr, "origImgPath": origImgPath}; return await compute(_processAsync, args); } static Future _release(int docFilterPtr) async { _nativeRelease(docFilterPtr); } static Future release(int docFilterPtr) async { return await compute(_release, docFilterPtr); } }