kotlin impl, avoid message passing overhead

This commit is contained in:
mertalev
2025-07-21 13:27:10 +03:00
parent ddd65dea58
commit f9687888b0
11 changed files with 264 additions and 132 deletions
+5 -9
View File
@@ -51,13 +51,14 @@ class ThumbnailApi {
final String pigeonVar_messageChannelSuffix;
Future<Uint8List> getThumbnail(
Future<void> setThumbnailToBuffer(
int pointer,
String assetId, {
required int width,
required int height,
}) async {
final String pigeonVar_channelName =
'dev.flutter.pigeon.immich_mobile.ThumbnailApi.getThumbnail$pigeonVar_messageChannelSuffix';
'dev.flutter.pigeon.immich_mobile.ThumbnailApi.setThumbnailToBuffer$pigeonVar_messageChannelSuffix';
final BasicMessageChannel<Object?> pigeonVar_channel =
BasicMessageChannel<Object?>(
pigeonVar_channelName,
@@ -65,7 +66,7 @@ class ThumbnailApi {
binaryMessenger: pigeonVar_binaryMessenger,
);
final Future<Object?> pigeonVar_sendFuture =
pigeonVar_channel.send(<Object?>[assetId, width, height]);
pigeonVar_channel.send(<Object?>[pointer, assetId, width, height]);
final List<Object?>? pigeonVar_replyList =
await pigeonVar_sendFuture as List<Object?>?;
if (pigeonVar_replyList == null) {
@@ -76,13 +77,8 @@ class ThumbnailApi {
message: pigeonVar_replyList[1] as String?,
details: pigeonVar_replyList[2],
);
} else if (pigeonVar_replyList[0] == null) {
throw PlatformException(
code: 'null-error',
message: 'Host platform returned null value for non-null return value.',
);
} else {
return (pigeonVar_replyList[0] as Uint8List?)!;
return;
}
}
}
@@ -1,3 +1,5 @@
import 'dart:ffi';
import 'package:flutter/material.dart';
import 'dart:async';
import 'dart:convert';
@@ -15,12 +17,13 @@ import 'package:immich_mobile/services/api.service.dart';
import 'package:immich_mobile/utils/image_url_builder.dart';
import 'package:logging/logging.dart';
import 'package:thumbhash/thumbhash.dart' as thumbhash;
import 'package:ffi/ffi.dart';
final log = Logger('ThumbnailWidget');
class Thumbnail extends StatefulWidget {
final BoxFit fit;
final Size size;
final ui.Size size;
final String? blurhash;
final String? localId;
final String? remoteId;
@@ -28,7 +31,7 @@ class Thumbnail extends StatefulWidget {
const Thumbnail({
this.fit = BoxFit.cover,
this.size = const Size.square(256),
this.size = const ui.Size.square(256),
this.blurhash,
this.localId,
this.remoteId,
@@ -39,7 +42,7 @@ class Thumbnail extends StatefulWidget {
Thumbnail.fromAsset({
required Asset asset,
this.fit = BoxFit.cover,
this.size = const Size.square(256),
this.size = const ui.Size.square(256),
this.thumbhashOnly = false,
super.key,
}) : blurhash = asset.thumbhash,
@@ -49,7 +52,7 @@ class Thumbnail extends StatefulWidget {
Thumbnail.fromBaseAsset({
required BaseAsset? asset,
this.fit = BoxFit.cover,
this.size = const Size.square(256),
this.size = const ui.Size.square(256),
this.thumbhashOnly = false,
super.key,
}) : blurhash = switch (asset) {
@@ -188,25 +191,38 @@ class _ThumbnailState extends State<Thumbnail> {
return null;
}
final stopwatch = Stopwatch()..start();
final thumb = await _decodeThumbnail(buffer, 256);
final thumb = await _decodeThumbnail(buffer, 256, 256);
stopwatch.stop();
return thumb;
}
Future<ui.Image?> _decodeThumbnail(ImmutableBuffer buffer, int height) async {
Future<ui.Image?> _decodeThumbnail(
ImmutableBuffer buffer,
int width,
int height,
) async {
if (!mounted) {
buffer.dispose();
return null;
}
final descriptor = await ImageDescriptor.encoded(buffer);
final descriptor = ImageDescriptor.raw(
buffer,
width: width,
height: height,
pixelFormat: PixelFormat.rgba8888,
);
if (!mounted) {
buffer.dispose();
descriptor.dispose();
return null;
}
final codec = await descriptor.instantiateCodec(targetHeight: height);
final codec = await descriptor.instantiateCodec(
targetWidth: width,
targetHeight: height,
);
if (!mounted) {
buffer.dispose();
@@ -231,16 +247,24 @@ class _ThumbnailState extends State<Thumbnail> {
final stopwatch = Stopwatch()..start();
final localId = widget.localId;
if (localId != null) {
final size = 256 * 256 * 4;
final pointer = malloc<Uint8>(size);
try {
final data =
await thumbnailApi.getThumbnail(localId, width: 256, height: 256);
await thumbnailApi.setThumbnailToBuffer(
pointer.address,
localId,
width: 256,
height: 256,
);
stopwatch.stop();
log.info(
'Retrieved local image $localId in ${stopwatch.elapsedMilliseconds.toStringAsFixed(2)} ms',
);
return ImmutableBuffer.fromUint8List(data);
return ImmutableBuffer.fromUint8List(pointer.asTypedList(size));
} catch (e) {
log.warning('Failed to retrieve local image $localId: $e');
} finally {
malloc.free(pointer);
}
}