diff --git a/lib/utils/resize_image.dart b/lib/utils/resize_image.dart index 102c78b4..2ae855fe 100644 --- a/lib/utils/resize_image.dart +++ b/lib/utils/resize_image.dart @@ -4,102 +4,56 @@ import 'dart:typed_data'; import 'package:famedlysdk/famedlysdk.dart'; import 'package:native_imaging/native_imaging.dart' as native; -import 'run_in_background.dart'; - Future resizeImage(MatrixImageFile file, {int max = 800}) async { - // we want to resize the image in a separate isolate, because otherwise that can - // freeze up the UI a bit - - // we can't do width / height fetching in a separate isolate, as that may use the UI stuff await native.init(); - _IsolateArgs args; - try { - final nativeImg = native.Image(); - await nativeImg.loadEncoded(file.bytes); - file.width = nativeImg.width; - file.height = nativeImg.height; - args = _IsolateArgs( - width: file.width, height: file.height, bytes: file.bytes, max: max); - nativeImg.free(); - } on UnsupportedError { - final dartCodec = await instantiateImageCodec(file.bytes); - final dartFrame = await dartCodec.getNextFrame(); - file.width = dartFrame.image.width; - file.height = dartFrame.image.height; - final rgbaData = await dartFrame.image.toByteData(); - final rgba = Uint8List.view( - rgbaData.buffer, rgbaData.offsetInBytes, rgbaData.lengthInBytes); - dartFrame.image.dispose(); - dartCodec.dispose(); - args = _IsolateArgs( - width: file.width, height: file.height, bytes: rgba, max: max); - } - - final res = await runInBackground(_isolateFunction, args); - file.blurhash = res.blurhash; - final thumbnail = MatrixImageFile( - bytes: res.jpegBytes, - name: file.name != null - ? 'scaled_' + file.name.split('.').first + '.jpg' - : 'thumbnail.jpg', - mimeType: 'image/jpeg', - width: res.width, - height: res.height, - ); - // only return the thumbnail if the size actually decreased - return thumbnail.size >= file.size ? file : thumbnail; -} - -class _IsolateArgs { - final int width; - final int height; - final Uint8List bytes; - final int max; - final String name; - _IsolateArgs({this.width, this.height, this.bytes, this.max, this.name}); -} - -class _IsolateResponse { - final String blurhash; - final Uint8List jpegBytes; - final int width; - final int height; - _IsolateResponse({this.blurhash, this.jpegBytes, this.width, this.height}); -} - -Future<_IsolateResponse> _isolateFunction(_IsolateArgs args) async { - await native.init(); var nativeImg = native.Image(); - try { - await nativeImg.loadEncoded(args.bytes); - } on UnsupportedError { - nativeImg.loadRGBA(args.width, args.height, args.bytes); - } - if (args.width > args.max || args.height > args.max) { - var w = args.max, h = args.max; - if (args.width > args.height) { - h = args.max * args.height ~/ args.width; - } else { - w = args.max * args.width ~/ args.height; + try { + await nativeImg.loadEncoded(file.bytes); + file.width = nativeImg.width; + file.height = nativeImg.height; + } on UnsupportedError { + final dartCodec = await instantiateImageCodec(file.bytes); + final dartFrame = await dartCodec.getNextFrame(); + file.width = dartFrame.image.width; + file.height = dartFrame.image.height; + final rgbaData = await dartFrame.image.toByteData(); + final rgba = Uint8List.view( + rgbaData.buffer, rgbaData.offsetInBytes, rgbaData.lengthInBytes); + dartFrame.image.dispose(); + dartCodec.dispose(); + nativeImg.loadRGBA(file.width, file.height, rgba); } - final scaledImg = nativeImg.resample(w, h, native.Transform.lanczos); + if (file.width > max || file.height > max) { + var w = max, h = max; + if (file.width > file.height) { + h = max * file.height ~/ file.width; + } else { + w = max * file.width ~/ file.height; + } + + final scaledImg = + await nativeImg.resample(w, h, native.Transform.lanczos); + nativeImg.free(); + nativeImg = scaledImg; + } + + final jpegBytes = await nativeImg.toJpeg(75); + file.blurhash = await nativeImg.toBlurhash(3, 3); + + return (jpegBytes.length > file.size ~/ 2) + ? null + : MatrixImageFile( + bytes: jpegBytes, + name: 'thumbnail.jpg', + mimeType: 'image/jpeg', + width: nativeImg.width, + height: nativeImg.height, + ); + } finally { nativeImg.free(); - nativeImg = scaledImg; } - final jpegBytes = await nativeImg.toJpeg(75); - final blurhash = nativeImg.toBlurhash(3, 3); - - final ret = _IsolateResponse( - blurhash: blurhash, - jpegBytes: jpegBytes, - width: nativeImg.width, - height: nativeImg.height); - - nativeImg.free(); - - return ret; } diff --git a/pubspec.lock b/pubspec.lock index cc8eab9f..4b1fc283 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -566,8 +566,8 @@ packages: dependency: "direct main" description: path: "." - ref: master - resolved-ref: c8eb59c25c4e3a568bd64e4722108ec45259e157 + ref: isolate + resolved-ref: fc24ec9888d32aee082c98cb8451b3cfd6cf4fe1 url: "https://gitlab.com/famedly/libraries/native_imaging.git" source: git version: "0.0.1" diff --git a/pubspec.yaml b/pubspec.yaml index 5dfbe566..1851aa44 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -67,7 +67,7 @@ dependencies: native_imaging: git: url: https://gitlab.com/famedly/libraries/native_imaging.git - ref: master + ref: isolate flutter_blurhash: ^0.5.0 sentry: ">=3.0.0 <4.0.0" scroll_to_index: ^1.0.6