feat(service): Massively speed up BlurHash calculation

This commit is contained in:
PapaTutuWawa 2022-10-05 17:09:23 +02:00
parent 18a9419cef
commit d81586d026
2 changed files with 33 additions and 10 deletions

View File

@ -1,23 +1,25 @@
import 'dart:io'; import 'dart:io';
import 'dart:typed_data'; import 'dart:typed_data';
import 'dart:ui'; import 'dart:ui';
import 'package:flutter/foundation.dart';
import 'package:native_imaging/native_imaging.dart' as native; import 'package:native_imaging/native_imaging.dart' as native;
/// Generate a blurhash thumbnail using native_imaging. Future<String?> _generateBlurhashThumbnailImpl(String path) async {
Future<String?> generateBlurhashThumbnail(String path) async {
await native.init(); await native.init();
final bytes = await File(path).readAsBytes(); final bytes = await File(path).readAsBytes();
native.Image image; native.Image image;
int width;
int height;
try { try {
final dartCodec = await instantiateImageCodec(bytes); final dartCodec = await instantiateImageCodec(bytes);
final dartFrame = await dartCodec.getNextFrame(); final dartFrame = await dartCodec.getNextFrame();
final rgbaData = await dartFrame.image.toByteData(); final rgbaData = await dartFrame.image.toByteData();
if (rgbaData == null) return null; if (rgbaData == null) return null;
final width = dartFrame.image.width; width = dartFrame.image.width;
final height = dartFrame.image.height; height = dartFrame.image.height;
dartFrame.image.dispose(); dartFrame.image.dispose();
dartCodec.dispose(); dartCodec.dispose();
@ -36,7 +38,24 @@ Future<String?> generateBlurhashThumbnail(String path) async {
return null; return null;
} }
final blurhash = image.toBlurhash(3, 3); // Scale the image down as recommended by
// https://github.com/woltapp/blurhash#how-fast-is-encoding-decoding
final scaled = image.resample(
20,
(height * (width / height)).toInt(),
native.Transform.bilinear,
);
// Calculate the blurhash
final blurhash = scaled.toBlurhash(3, 3);
// Free resources
image.free(); image.free();
scaled.free();
return blurhash; return blurhash;
} }
/// Generate a blurhash thumbnail using native_imaging.
Future<String?> generateBlurhashThumbnail(String path) async {
return compute(_generateBlurhashThumbnailImpl, path);
}

View File

@ -419,11 +419,15 @@ class XmppService {
// TODO(Unknown): Do the same for videos // TODO(Unknown): Do the same for videos
if (pathMime != null && pathMime.startsWith('image/')) { if (pathMime != null && pathMime.startsWith('image/')) {
final imageSize = image_size.ImageSizeGetter.getSize(FileInput(File(path))); try {
dimensions[path] = Size( final imageSize = image_size.ImageSizeGetter.getSize(FileInput(File(path)));
imageSize.width.toDouble(), dimensions[path] = Size(
imageSize.height.toDouble(), imageSize.width.toDouble(),
); imageSize.height.toDouble(),
);
} catch (ex) {
_log.warning('Failed to get image dimensions for $path');
}
} }
final msg = await ms.addMessageFromData( final msg = await ms.addMessageFromData(