feat(service): Massively speed up BlurHash calculation
This commit is contained in:
parent
18a9419cef
commit
d81586d026
@ -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);
|
||||||
|
}
|
||||||
|
@ -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(
|
||||||
|
Loading…
Reference in New Issue
Block a user