浏览代码

[mob][photos] Use thumbnails for generating face crop in suggestions

laurenspriem 1 年之前
父节点
当前提交
29b9bee1be

+ 5 - 4
mobile/lib/ui/viewer/people/person_cluster_suggestion.dart

@@ -261,21 +261,21 @@ class _PersonClustersState extends State<PersonReviewClusterSuggestion> {
       ],
     );
     // Precompute face thumbnails for next suggestions, in case there are
-    const precompute = 6;
-    const maxComputations = 10;
+    const precomputeSuggestions = 6;
+    const maxPrecomputations = 10;
     int compCount = 0;
 
     if (allSuggestions.length > currentSuggestionIndex + 1) {
       for (final suggestion in allSuggestions.sublist(
         currentSuggestionIndex + 1,
-        min(allSuggestions.length, currentSuggestionIndex + precompute),
+        min(allSuggestions.length, currentSuggestionIndex + precomputeSuggestions),
       )) {
         final files = suggestion.filesInCluster;
         final clusterID = suggestion.clusterIDToMerge;
         for (final file in files.sublist(0, min(files.length, 8))) {
           unawaited(PersonFaceWidget.precomputeNextFaceCrops(file, clusterID));
           compCount++;
-          if (compCount >= maxComputations) {
+          if (compCount >= maxPrecomputations) {
             break;
           }
         }
@@ -300,6 +300,7 @@ class _PersonClustersState extends State<PersonReviewClusterSuggestion> {
             child: PersonFaceWidget(
               files[start + index],
               clusterID: cluserId,
+              useFullFile: false,
             ),
           ),
         ),

+ 16 - 2
mobile/lib/ui/viewer/search/result/person_face_widget.dart

@@ -19,6 +19,7 @@ class PersonFaceWidget extends StatelessWidget {
   final EnteFile file;
   final String? personId;
   final int? clusterID;
+  final bool useFullFile;
 
   // PersonFaceWidget constructor checks that both personId and clusterID are not null
   // and that the file is not null
@@ -26,6 +27,7 @@ class PersonFaceWidget extends StatelessWidget {
     this.file, {
     this.personId,
     this.clusterID,
+    this.useFullFile = true,
     Key? key,
   })  : assert(
           personId != null || clusterID != null,
@@ -176,6 +178,13 @@ class PersonFaceWidget extends StatelessWidget {
         faceCropCache.put(face.faceID, data);
         return data;
       }
+      if (!useFullFile) {
+        final Uint8List? cachedFaceThumbnail =
+            faceCropThumbnailCache.get(face.faceID);
+        if (cachedFaceThumbnail != null) {
+          return cachedFaceThumbnail;
+        }
+      }
       EnteFile? fileForFaceCrop = file;
       if (face.fileID != file.uploadedFileID!) {
         fileForFaceCrop =
@@ -191,12 +200,17 @@ class PersonFaceWidget extends StatelessWidget {
           {
             face.faceID: face.detection.box,
           },
+          useFullFile: useFullFile,
         ),
       );
       final Uint8List? computedCrop = result?[face.faceID];
       if (computedCrop != null) {
-        faceCropCache.put(face.faceID, computedCrop);
-        faceCropCacheFile.writeAsBytes(computedCrop).ignore();
+        if (useFullFile) {
+          faceCropCache.put(face.faceID, computedCrop);
+          faceCropCacheFile.writeAsBytes(computedCrop).ignore();
+        } else {
+          faceCropThumbnailCache.put(face.faceID, computedCrop);
+        }
       }
       return computedCrop;
     } catch (e, s) {

+ 11 - 8
mobile/lib/utils/face/face_box_crop.dart

@@ -1,4 +1,4 @@
-import "dart:io";
+import "dart:io" show File;
 
 import "package:flutter/foundation.dart";
 import "package:photos/core/cache/lru_map.dart";
@@ -12,24 +12,27 @@ import "package:photos/utils/thumbnail_util.dart";
 import "package:pool/pool.dart";
 
 final LRUMap<String, Uint8List?> faceCropCache = LRUMap(1000);
+final LRUMap<String, Uint8List?> faceCropThumbnailCache = LRUMap(1000);
 final pool = Pool(10, timeout: const Duration(seconds: 15));
 Future<Map<String, Uint8List>?> getFaceCrops(
   EnteFile file,
-  Map<String, FaceBox> faceBoxeMap,
+  Map<String, FaceBox> faceBoxeMap, {
+  bool useFullFile = true,
+  }
 ) async {
   late String? imagePath;
-  if (file.fileType != FileType.video) {
+  if (useFullFile && file.fileType != FileType.video) {
     final File? ioFile = await getFile(file);
     if (ioFile == null) {
       return null;
     }
     imagePath = ioFile.path;
   } else {
-    final thumbnail = await getThumbnailForUploadedFile(file);
-    if (thumbnail == null) {
-      return null;
-    }
-    imagePath = thumbnail.path;
+  final thumbnail = await getThumbnailForUploadedFile(file);
+  if (thumbnail == null) {
+    return null;
+  }
+  imagePath = thumbnail.path;
   }
   final List<String> faceIds = [];
   final List<FaceBox> faceBoxes = [];