diff --git a/mobile/lib/ui/viewer/people/cropped_face_image_view.dart b/mobile/lib/ui/viewer/people/cropped_face_image_view.dart index cb7baff42..0da4129eb 100644 --- a/mobile/lib/ui/viewer/people/cropped_face_image_view.dart +++ b/mobile/lib/ui/viewer/people/cropped_face_image_view.dart @@ -1,7 +1,10 @@ import "dart:io" show File; import 'dart:ui' as ui; +import "package:computer/computer.dart"; import 'package:flutter/material.dart'; +import "package:flutter/widgets.dart"; +import "package:flutter_image_compress/flutter_image_compress.dart"; import "package:image/image.dart" as img; import "package:logging/logging.dart"; import "package:photos/face/model/face.dart"; @@ -40,6 +43,7 @@ class CroppedFaceImageView extends StatefulWidget { class CroppedFaceImageViewState extends State { ui.Image? _image; + final _computer = Computer.shared(); final _logger = Logger("CroppedFaceImageView"); @override @@ -79,17 +83,32 @@ class CroppedFaceImageViewState extends State { Future getImage() async { try { final faceBox = widget.face.detection.box; + final File? ioFile = await getFile(widget.enteFile); if (ioFile == null) { return null; } - final image = await img.decodeImageFile(ioFile.path); + img.Image? image = await _computer + .compute(decodeImage, param: {"filePath": ioFile.path}); if (image == null) { - throw Exception("Failed decoding image file ${widget.enteFile.title}}"); + _logger.info( + "Failed to decode image ${widget.enteFile.title}. Compressing to jpg and decoding", + ); + final compressedJPGImage = + await FlutterImageCompress.compressWithFile(ioFile.path); + image = await _computer.compute( + decodeJPGImage, + param: {"image": compressedJPGImage}, + ); + + if (image == null) { + throw Exception("Failed to decode image"); + } } + final stopwatch = Stopwatch()..start(); final croppedImage = img.copyCrop( image, x: (image.width * faceBox.xMin).round(), @@ -98,7 +117,10 @@ class CroppedFaceImageViewState extends State { height: (image.height * faceBox.height).round(), antialias: false, ); - + _logger.info( + "Image crop took ${stopwatch.elapsedMilliseconds}ms ----------------", + ); + stopwatch.stop(); return convertImageToFlutterUi(croppedImage); } catch (e, s) { _logger.severe("Error getting image", e, s); @@ -106,3 +128,11 @@ class CroppedFaceImageViewState extends State { } } } + +Future decodeImage(Map args) async { + return await img.decodeImageFile(args["filePath"]); +} + +img.Image? decodeJPGImage(Map args) { + return img.decodeJpg(args["image"])!; +}