refactor: Make MatrixFile final and move all image calculation into isolate
This makes all fields in a MatrixFile final and the object therefore stateless. It also moves all calculations into the isolate. After some benchmarks it seems that this does not really speed up the thumbnail creation but it does no longer block the UI for some seconds.
This commit is contained in:
parent
6dbe62424d
commit
9fa5667234
|
|
@ -28,9 +28,9 @@ import 'package:mime/mime.dart';
|
|||
import '../../matrix.dart';
|
||||
|
||||
class MatrixFile {
|
||||
Uint8List bytes;
|
||||
String name;
|
||||
String mimeType;
|
||||
final Uint8List bytes;
|
||||
final String name;
|
||||
final String mimeType;
|
||||
|
||||
/// Encrypts this file and returns the
|
||||
/// encryption information as an [EncryptedFile].
|
||||
|
|
@ -66,14 +66,36 @@ class MatrixFile {
|
|||
}
|
||||
|
||||
class MatrixImageFile extends MatrixFile {
|
||||
Image? _image;
|
||||
|
||||
MatrixImageFile({
|
||||
required Uint8List bytes,
|
||||
required String name,
|
||||
String? mimeType,
|
||||
this.width,
|
||||
this.height,
|
||||
this.blurhash,
|
||||
}) : super(bytes: bytes, name: name, mimeType: mimeType);
|
||||
|
||||
/// Creates a new image file and calculates the width, height and blurhash.
|
||||
static Future<MatrixImageFile> create(
|
||||
{required Uint8List bytes,
|
||||
required String name,
|
||||
String? mimeType,
|
||||
Future<T> Function<T, U>(FutureOr<T> Function(U arg) function, U arg)?
|
||||
compute}) async {
|
||||
final metaData = compute != null
|
||||
? await compute(_calcMetadata, bytes)
|
||||
: _calcMetadata(bytes);
|
||||
|
||||
return MatrixImageFile(
|
||||
bytes: metaData?.bytes ?? bytes,
|
||||
name: name,
|
||||
mimeType: mimeType,
|
||||
width: metaData?.width,
|
||||
height: metaData?.height,
|
||||
blurhash: metaData?.blurhash,
|
||||
);
|
||||
}
|
||||
|
||||
/// builds a [MatrixImageFile] and shrinks it in order to reduce traffic
|
||||
///
|
||||
/// in case shrinking does not work (e.g. for unsupported MIME types), the
|
||||
|
|
@ -85,11 +107,11 @@ class MatrixImageFile extends MatrixFile {
|
|||
String? mimeType,
|
||||
Future<T> Function<T, U>(FutureOr<T> Function(U arg) function, U arg)?
|
||||
compute}) async {
|
||||
Image? image;
|
||||
final arguments = _ResizeArguments(
|
||||
bytes: bytes,
|
||||
maxDimension: maxDimension,
|
||||
fileName: name,
|
||||
calcBlurhash: true,
|
||||
);
|
||||
final resizedData = compute != null
|
||||
? await compute(_resize, arguments)
|
||||
|
|
@ -98,48 +120,26 @@ class MatrixImageFile extends MatrixFile {
|
|||
if (resizedData == null) {
|
||||
return MatrixImageFile(bytes: bytes, name: name, mimeType: mimeType);
|
||||
}
|
||||
image = decodeImage(resizedData);
|
||||
|
||||
if (image == null) {
|
||||
return MatrixImageFile(bytes: bytes, name: name, mimeType: mimeType);
|
||||
}
|
||||
|
||||
final encoded = encodeNamedImage(image, name);
|
||||
if (encoded == null) {
|
||||
return MatrixImageFile(bytes: bytes, name: name, mimeType: mimeType);
|
||||
}
|
||||
|
||||
final thumbnailFile = MatrixImageFile(
|
||||
bytes: Uint8List.fromList(encoded),
|
||||
bytes: resizedData.bytes,
|
||||
name: name,
|
||||
mimeType: mimeType,
|
||||
width: resizedData.width,
|
||||
height: resizedData.height,
|
||||
blurhash: resizedData.blurhash,
|
||||
);
|
||||
// preserving the previously generated image
|
||||
thumbnailFile._image = image;
|
||||
return thumbnailFile;
|
||||
}
|
||||
|
||||
/// returns the width of the image
|
||||
int? get width {
|
||||
_image ??= decodeImage(bytes);
|
||||
return _image?.width;
|
||||
}
|
||||
final int? width;
|
||||
|
||||
/// returns the height of the image
|
||||
int? get height {
|
||||
_image ??= decodeImage(bytes);
|
||||
return _image?.height;
|
||||
}
|
||||
final int? height;
|
||||
|
||||
/// generates the blur hash for the image
|
||||
String? get blurhash {
|
||||
_image ??= decodeImage(bytes)!;
|
||||
if (_image != null) {
|
||||
final blur = BlurHash.encode(_image!, numCompX: 4, numCompY: 3);
|
||||
return blur.hash;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
final String? blurhash;
|
||||
|
||||
@override
|
||||
String get msgType => 'm.image';
|
||||
|
|
@ -171,7 +171,23 @@ class MatrixImageFile extends MatrixFile {
|
|||
return thumbnailFile;
|
||||
}
|
||||
|
||||
static Uint8List? _resize(_ResizeArguments arguments) {
|
||||
static _ResizedResponse? _calcMetadata(Uint8List bytes) {
|
||||
final image = decodeImage(bytes);
|
||||
if (image == null) return null;
|
||||
|
||||
return _ResizedResponse(
|
||||
bytes: bytes,
|
||||
width: image.width,
|
||||
height: image.height,
|
||||
blurhash: BlurHash.encode(
|
||||
image,
|
||||
numCompX: 4,
|
||||
numCompY: 3,
|
||||
).hash,
|
||||
);
|
||||
}
|
||||
|
||||
static _ResizedResponse? _resize(_ResizeArguments arguments) {
|
||||
final image = decodeImage(arguments.bytes);
|
||||
|
||||
final resized = copyResize(image!,
|
||||
|
|
@ -180,26 +196,54 @@ class MatrixImageFile extends MatrixFile {
|
|||
|
||||
final encoded = encodeNamedImage(resized, arguments.fileName);
|
||||
if (encoded == null) return null;
|
||||
return Uint8List.fromList(encoded);
|
||||
final bytes = Uint8List.fromList(encoded);
|
||||
return _ResizedResponse(
|
||||
bytes: bytes,
|
||||
width: resized.width,
|
||||
height: resized.height,
|
||||
blurhash: arguments.calcBlurhash
|
||||
? BlurHash.encode(
|
||||
resized,
|
||||
numCompX: 4,
|
||||
numCompY: 3,
|
||||
).hash
|
||||
: null,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _ResizedResponse {
|
||||
final Uint8List bytes;
|
||||
final int width;
|
||||
final int height;
|
||||
final String? blurhash;
|
||||
|
||||
const _ResizedResponse({
|
||||
required this.bytes,
|
||||
required this.width,
|
||||
required this.height,
|
||||
this.blurhash,
|
||||
});
|
||||
}
|
||||
|
||||
class _ResizeArguments {
|
||||
final Uint8List bytes;
|
||||
final int maxDimension;
|
||||
final String fileName;
|
||||
final bool calcBlurhash;
|
||||
|
||||
const _ResizeArguments({
|
||||
required this.bytes,
|
||||
required this.maxDimension,
|
||||
required this.fileName,
|
||||
required this.calcBlurhash,
|
||||
});
|
||||
}
|
||||
|
||||
class MatrixVideoFile extends MatrixFile {
|
||||
int? width;
|
||||
int? height;
|
||||
int? duration;
|
||||
final int? width;
|
||||
final int? height;
|
||||
final int? duration;
|
||||
|
||||
MatrixVideoFile(
|
||||
{required Uint8List bytes,
|
||||
|
|
@ -221,7 +265,7 @@ class MatrixVideoFile extends MatrixFile {
|
|||
}
|
||||
|
||||
class MatrixAudioFile extends MatrixFile {
|
||||
int? duration;
|
||||
final int? duration;
|
||||
|
||||
MatrixAudioFile(
|
||||
{required Uint8List bytes,
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ void main() {
|
|||
'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';
|
||||
final data = base64Decode(base64Image);
|
||||
|
||||
final image = MatrixImageFile(
|
||||
final image = await MatrixImageFile.create(
|
||||
bytes: data,
|
||||
name: 'bomb.png',
|
||||
mimeType: 'image/png',
|
||||
|
|
|
|||
Loading…
Reference in New Issue