mirror of
https://github.com/kodjodevf/mangayomi.git
synced 2026-03-11 17:25:32 +00:00
Add image cropping functionality with isolate support and optimize crop border processing
This commit is contained in:
parent
f483dfab2b
commit
6e94632417
3 changed files with 116 additions and 6 deletions
|
|
@ -22,6 +22,7 @@ import 'package:mangayomi/models/track.dart' as track;
|
|||
import 'package:mangayomi/models/track_preference.dart';
|
||||
import 'package:mangayomi/models/track_search.dart';
|
||||
import 'package:mangayomi/modules/manga/detail/providers/track_state_providers.dart';
|
||||
import 'package:mangayomi/modules/manga/reader/providers/crop_borders_provider.dart';
|
||||
import 'package:mangayomi/modules/more/data_and_storage/providers/storage_usage.dart';
|
||||
import 'package:mangayomi/modules/more/settings/browse/providers/browse_state_provider.dart';
|
||||
import 'package:mangayomi/modules/more/settings/general/providers/general_state_provider.dart';
|
||||
|
|
@ -52,6 +53,7 @@ void main(List<String> args) async {
|
|||
if (Platform.isLinux && runWebViewTitleBarWidget(args)) return;
|
||||
MediaKit.ensureInitialized();
|
||||
await RustLib.init();
|
||||
await imgCropIsolate.start();
|
||||
if (!(Platform.isAndroid || Platform.isIOS)) {
|
||||
await windowManager.ensureInitialized();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,12 +23,119 @@ Future<Uint8List?> cropBorders(
|
|||
return null;
|
||||
}
|
||||
|
||||
return await Isolate.run(() async {
|
||||
await RustLib.init();
|
||||
final imageRes = processCropImage(image: imageBytes!);
|
||||
RustLib.dispose();
|
||||
return imageRes;
|
||||
});
|
||||
return imgCropIsolate.process(imageBytes);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
class ImageCropIsolate {
|
||||
bool _isRunning = false;
|
||||
Isolate? _rustIsolate;
|
||||
ReceivePort? _receivePort;
|
||||
SendPort? _sendPort;
|
||||
|
||||
Future<void> start() async {
|
||||
if (!_isRunning) {
|
||||
try {
|
||||
await _initRustIsolate();
|
||||
} catch (_) {
|
||||
await stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _initRustIsolate() async {
|
||||
_receivePort = ReceivePort();
|
||||
|
||||
_rustIsolate = await Isolate.spawn(
|
||||
_rustIsolateEntryPoint,
|
||||
_receivePort!.sendPort,
|
||||
);
|
||||
|
||||
final completer = Completer<SendPort>();
|
||||
_receivePort!.listen((message) {
|
||||
if (message is SendPort) {
|
||||
completer.complete(message);
|
||||
}
|
||||
});
|
||||
|
||||
_sendPort = await completer.future;
|
||||
_isRunning = true;
|
||||
}
|
||||
|
||||
static Future<void> _rustIsolateEntryPoint(SendPort mainSendPort) async {
|
||||
await RustLib.init();
|
||||
|
||||
final receivePort = ReceivePort();
|
||||
mainSendPort.send(receivePort.sendPort);
|
||||
|
||||
await for (var message in receivePort) {
|
||||
if (message is Map<String, dynamic>) {
|
||||
try {
|
||||
final imageBytes = message['imageBytes'] as Uint8List;
|
||||
final responsePort = message['responsePort'] as SendPort;
|
||||
|
||||
final croppedImage = processCropImage(image: imageBytes);
|
||||
|
||||
responsePort.send({'success': true, 'data': croppedImage});
|
||||
} catch (e) {
|
||||
final responsePort = message['responsePort'] as SendPort;
|
||||
responsePort.send({'success': false, 'error': e.toString()});
|
||||
}
|
||||
} else if (message == 'dispose') {
|
||||
RustLib.dispose();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Future<Uint8List?> process(Uint8List imageBytes) async {
|
||||
await start();
|
||||
if (_sendPort == null) {
|
||||
if (kDebugMode) {
|
||||
print('Image crop isolate is not running');
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
final responsePort = ReceivePort();
|
||||
final completer = Completer<Uint8List?>();
|
||||
|
||||
responsePort.listen((response) {
|
||||
responsePort.close();
|
||||
if (response is Map<String, dynamic>) {
|
||||
if (response['success'] == true) {
|
||||
completer.complete(response['data'] as Uint8List);
|
||||
} else {
|
||||
if (kDebugMode) {
|
||||
print('Image cropping failed: ${response['error']}');
|
||||
}
|
||||
completer.complete(Future.value(null));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
_sendPort!.send({
|
||||
'imageBytes': imageBytes,
|
||||
'responsePort': responsePort.sendPort,
|
||||
});
|
||||
|
||||
return completer.future;
|
||||
}
|
||||
|
||||
Future<void> stop() async {
|
||||
if (!_isRunning) {
|
||||
return;
|
||||
}
|
||||
|
||||
_sendPort?.send('dispose');
|
||||
_rustIsolate?.kill(priority: Isolate.immediate);
|
||||
_receivePort?.close();
|
||||
_sendPort = null;
|
||||
_rustIsolate = null;
|
||||
_receivePort = null;
|
||||
_isRunning = false;
|
||||
}
|
||||
}
|
||||
|
||||
final imgCropIsolate = ImageCropIsolate();
|
||||
|
|
|
|||
|
|
@ -1397,6 +1397,7 @@ class _MangaChapterPageGalleryState
|
|||
}
|
||||
|
||||
void _processCropBorders() async {
|
||||
if (_cropBorderCheckList.length == _uChapDataPreload.length) return;
|
||||
for (var i = 0; i < _uChapDataPreload.length; i++) {
|
||||
if (!_cropBorderCheckList.contains(i)) {
|
||||
_cropBorderCheckList.add(i);
|
||||
|
|
|
|||
Loading…
Reference in a new issue