Files
flutter_opencv_native/lib/main.dart
2021-11-17 14:57:56 -06:00

177 lines
4.7 KiB
Dart

import 'dart:async';
import 'dart:io';
import 'dart:isolate';
import 'package:file_picker/file_picker.dart';
import 'package:flutter/material.dart';
import 'package:flutter_ffmpeg/stream_information.dart';
import 'package:flutter_opencv_example/native_opencv.dart';
import 'package:path_provider/path_provider.dart';
import 'package:flutter_ffmpeg/flutter_ffmpeg.dart';
const title = 'Native OpenCV Example';
late Directory tempDir;
String get dataPath => '${tempDir.path}/data.csv';
void main() {
WidgetsFlutterBinding.ensureInitialized();
getTemporaryDirectory().then((dir) => tempDir = dir);
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: title,
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
bool _isProcessed = false;
bool _isWorking = false;
void showVersion() {
final scaffoldMessenger = ScaffoldMessenger.of(context);
final snackbar = SnackBar(
content: Text('OpenCV version: ${opencvVersion()}'),
);
scaffoldMessenger
..removeCurrentSnackBar(reason: SnackBarClosedReason.dismiss)
..showSnackBar(snackbar);
}
Future<String?> pickAnImage() async {
if (Platform.isIOS || Platform.isAndroid) {
return FilePicker.platform
.pickFiles(
dialogTitle: 'Pick an image',
type: FileType.video,
allowMultiple: false,
)
.then((v) => v?.files.first.path);
} else {
return FilePicker.platform
.pickFiles(
dialogTitle: 'Pick an image',
type: FileType.image,
allowMultiple: false,
)
.then((v) => v?.files.first.path);
}
}
Future<void> takeImageAndProcess() async {
final imagePath = await pickAnImage();
final FlutterFFprobe _flutterFFmpeg = FlutterFFprobe();
if (imagePath == null) {
return;
}
double? frameRate;
var vinfo = await _flutterFFmpeg.getMediaInformation(imagePath);
List<StreamInformation>? streams = vinfo.getStreams();
if (streams!.length > 0) {
for (var stream in streams) {
if (stream.getAllProperties()['codec_type'] == "video") {
frameRate = int.parse(
stream.getAllProperties()['avg_frame_rate'].split("/")[0]) /
int.parse(
stream.getAllProperties()['avg_frame_rate'].split("/")[1]);
}
}
}
setState(() {
_isWorking = true;
});
// Creating a port for communication with isolate and arguments for entry point
final port = ReceivePort();
final args = ProcessImageArguments(imagePath, dataPath, frameRate ?? 0.0);
// Spawning an isolate
Isolate.spawn<ProcessImageArguments>(
processImage,
args,
onError: port.sendPort,
onExit: port.sendPort,
);
// Making a variable to store a subscription in
late StreamSubscription sub;
// Listening for messages on port
sub = port.listen((_) async {
// Cancel a subscription after message received called
await sub.cancel();
setState(() {
_isProcessed = true;
_isWorking = false;
});
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text(title)),
body: Stack(
children: <Widget>[
Center(
child: ListView(
shrinkWrap: true,
children: <Widget>[
if (_isProcessed && !_isWorking)
ConstrainedBox(
constraints: BoxConstraints(maxWidth: 3000, maxHeight: 300),
// child: Image.file(
// File(tempPath),
// alignment: Alignment.center,
// ),
),
Column(
children: [
ElevatedButton(
child: Text('Show version'),
onPressed: showVersion,
),
ElevatedButton(
child: Text('Process photo'),
onPressed: takeImageAndProcess,
),
],
)
],
),
),
if (_isWorking)
Positioned.fill(
child: Container(
color: Colors.black.withOpacity(.7),
child: Center(
child: CircularProgressIndicator(),
),
),
),
],
),
);
}
}