-
-
Notifications
You must be signed in to change notification settings - Fork 313
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix: 3964 - text messages instead of circular indicator for crop page…
… + isolate (#3965) Impacted files: * `app_en.arb`: added 5 labels for the action progress on crop page * `background_task_image.dart`: minor refactoring * `crop_page.dart`: displays a text instead of a stuttering circular progress indicator; minor refatoring * `image_compute_container.dart`: now using `compute` as much as possible - still not possible for `ui`
- Loading branch information
1 parent
b59d19f
commit 1af41f2
Showing
4 changed files
with
137 additions
and
53 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
140 changes: 98 additions & 42 deletions
140
packages/smooth_app/lib/helpers/image_compute_container.dart
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,65 +1,121 @@ | ||
import 'dart:async'; | ||
import 'dart:io'; | ||
import 'dart:typed_data'; | ||
import 'dart:ui' as ui; | ||
|
||
import 'package:flutter/foundation.dart'; | ||
import 'package:flutter_image_compress/flutter_image_compress.dart'; | ||
import 'package:image/image.dart' as image; | ||
|
||
// TODO(monsieurtanuki): try to use simple isolates with `compute` | ||
/// Container for Image Compute and Compress operations. | ||
class ImageComputeContainer { | ||
const ImageComputeContainer({ | ||
class _ImageComputeContainer { | ||
_ImageComputeContainer({ | ||
required this.file, | ||
required this.source, | ||
required this.rawData, | ||
required this.width, | ||
required this.height, | ||
}); | ||
|
||
final File file; | ||
final ui.Image source; | ||
//final image.Image rawImage; | ||
final ByteData rawData; | ||
final int width; | ||
final int height; | ||
} | ||
|
||
Future<image.Image> _convertImageFromUI() async { | ||
final ByteData? rawData = await source.toByteData( | ||
format: ui.ImageByteFormat.rawRgba, | ||
); | ||
if (rawData == null) { | ||
throw Exception('Cannot convert file'); | ||
} | ||
// TODO(monsieurtanuki): perhaps a bit slow, which would call for a isolate/compute | ||
return image.Image.fromBytes( | ||
/// Saves an image to a BMP file. As BMP for better performances. | ||
Future<void> saveBmp({ | ||
required final File file, | ||
required final ui.Image source, | ||
}) async { | ||
final ByteData? rawData = await source.toByteData( | ||
format: ui.ImageByteFormat.rawRgba, | ||
); | ||
if (rawData == null) { | ||
throw Exception('Cannot convert file'); | ||
} | ||
await compute( | ||
_saveBmp, | ||
_ImageComputeContainer( | ||
file: file, | ||
rawData: rawData, | ||
width: source.width, | ||
height: source.height, | ||
), | ||
); | ||
} | ||
|
||
/// Saves an image to a JPEG file. | ||
/// | ||
/// It's faster to encode as BMP and then compress to JPEG, instead of directly | ||
/// compressing the image to JPEG (standard flutter being slow). | ||
Future<void> saveJpeg({ | ||
required final File file, | ||
required final ui.Image source, | ||
}) async { | ||
final ByteData? rawData = await source.toByteData( | ||
format: ui.ImageByteFormat.rawRgba, | ||
); | ||
if (rawData == null) { | ||
throw Exception('Cannot convert file'); | ||
} | ||
await compute( | ||
_saveJpeg, | ||
_ImageComputeContainer( | ||
file: file, | ||
rawData: rawData, | ||
width: source.width, | ||
height: source.height, | ||
), | ||
); | ||
} | ||
|
||
Future<image.Image> _convertImageFromUI( | ||
final ByteData rawData, | ||
final int width, | ||
final int height, | ||
) async => | ||
image.Image.fromBytes( | ||
width: width, | ||
height: height, | ||
bytes: rawData.buffer, | ||
format: image.Format.uint8, | ||
order: image.ChannelOrder.rgba, | ||
); | ||
} | ||
|
||
/// Saves an image to a BMP file. As BMP for better performances. | ||
Future<void> saveBmp() async { | ||
final image.Image rawImage = await _convertImageFromUI(); | ||
await file.writeAsBytes( | ||
image.encodeBmp(rawImage), | ||
flush: true, | ||
); | ||
} | ||
/// Saves an image to a BMP file. As BMP for better performances. | ||
Future<void> _saveBmp(final _ImageComputeContainer container) async { | ||
final image.Image rawImage = await _convertImageFromUI( | ||
container.rawData, | ||
container.width, | ||
container.height, | ||
); | ||
await container.file.writeAsBytes( | ||
image.encodeBmp(rawImage), | ||
flush: true, | ||
); | ||
} | ||
|
||
/// Saves an image to a JPEG file. | ||
/// | ||
/// It's faster to encode as BMP and then compress to JPEG, instead of directly | ||
/// compressing the image to JPEG (standard flutter being slow). | ||
Future<void> saveJpeg() async { | ||
final image.Image rawImage = await _convertImageFromUI(); | ||
final Uint8List bmpData = Uint8List.fromList(image.encodeBmp(rawImage)); | ||
final Uint8List jpegData = await FlutterImageCompress.compressWithList( | ||
bmpData, | ||
autoCorrectionAngle: false, | ||
quality: 100, | ||
format: CompressFormat.jpeg, | ||
minWidth: rawImage.width, | ||
minHeight: rawImage.height, | ||
); | ||
await file.writeAsBytes(jpegData, flush: true); | ||
} | ||
/// Saves an image to a JPEG file. | ||
/// | ||
/// It's faster to encode as BMP and then compress to JPEG, instead of directly | ||
/// compressing the image to JPEG (standard flutter being slow). | ||
Future<void> _saveJpeg(final _ImageComputeContainer container) async { | ||
image.Image? rawImage = await _convertImageFromUI( | ||
container.rawData, | ||
container.width, | ||
container.height, | ||
); | ||
Uint8List? bmpData = Uint8List.fromList(image.encodeBmp(rawImage)); | ||
// gc? | ||
rawImage = null; | ||
final Uint8List jpegData = await FlutterImageCompress.compressWithList( | ||
bmpData, | ||
autoCorrectionAngle: false, | ||
quality: 100, | ||
format: CompressFormat.jpeg, | ||
minWidth: container.width, | ||
minHeight: container.height, | ||
); | ||
// gc? | ||
bmpData = null; | ||
await container.file.writeAsBytes(jpegData, flush: true); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters