Last active
January 5, 2023 13:29
-
-
Save alexmercerind/688b73fdfdc33e0bf1937604ded13afa to your computer and use it in GitHub Desktop.
crop image to square in Dart
This file contains hidden or 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
import 'dart:io'; | |
import 'dart:math'; | |
import 'dart:isolate'; | |
import 'package:image/image.dart'; | |
import 'package:http/http.dart' as http; | |
import 'package:flutter/foundation.dart'; | |
import 'package:safe_local_storage/safe_local_storage.dart'; | |
/// This method crops passed given [image] into square & returns it | |
/// as [Uint8List] in JPEG format. | |
/// The passed [image] may be: | |
/// * [Uri] or [String] - URL to the image. | |
/// * [File] - local file. | |
/// * [Uint8List] or [List<int>] - encoded image data. | |
/// | |
/// The method is asynchronous & works on separate isolate & thus, performant. | |
/// | |
/// This is specifically used in the native notifications i.e. System Media Transport Controls, MPRIS & Android Media Session. | |
/// | |
Future<Uint8List?> imageCropSquare(dynamic image) async { | |
final receivePort = ReceivePort(); | |
await Isolate.spawn( | |
_cropSquareIsolate, | |
_DecodeParam( | |
image, | |
receivePort.sendPort, | |
), | |
); | |
final result = await receivePort.first; | |
receivePort.close(); | |
assert(result is Uint8List || result == null); | |
return result; | |
} | |
/// Used for packing parameters for [_cropSquareIsolate] method. | |
class _DecodeParam { | |
final dynamic image; | |
final SendPort sendPort; | |
_DecodeParam( | |
this.image, | |
this.sendPort, | |
); | |
} | |
/// Method spawned on another isolate for [imageCropSquare]. | |
/// | |
/// Returns `null` if passed [data.image] is in unknown format or | |
/// original image if some other error is received. | |
/// | |
void _cropSquareIsolate(_DecodeParam data) async { | |
Uint8List? buffer; | |
if (data.image is Uint8List || data.image is List<int>) { | |
buffer = data.image; | |
} else if (data.image is Uri || data.image is String) { | |
try { | |
final response = await http.get( | |
data.image is Uri ? data.image : Uri.parse(data.image), | |
); | |
buffer = response.bodyBytes; | |
} catch (exception, stacktrace) { | |
debugPrint(exception.toString()); | |
debugPrint(stacktrace.toString()); | |
} | |
} else if (data.image is File) { | |
try { | |
buffer = await (data.image as File).readAsBytes_(); | |
} catch (exception, stacktrace) { | |
debugPrint(exception.toString()); | |
debugPrint(stacktrace.toString()); | |
} | |
} | |
if (buffer != null) { | |
try { | |
final image = decodeImage(buffer); | |
if (image != null && image.width != 0 && image.height != 0) { | |
final dimension = min(image.width, image.height); | |
final result = copyResizeCropSquare(image, dimension); | |
data.sendPort.send(encodeJpg(result)); | |
} | |
return data.sendPort.send(buffer); | |
} catch (exception, stacktrace) { | |
debugPrint(exception.toString()); | |
debugPrint(stacktrace.toString()); | |
} | |
} | |
data.sendPort.send(null); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment