mdanics/fluttergram

copyResize method is locking UI

GustavoContreiras opened this issue · 2 comments

The last time I downloaded this project, the compressImage method was calling copyResize from image package and this was locking the UI cause flutter uses a single thread.

Here is the solution:
https://github.com/brendan-duncan/image/wiki/Examples

Edit: old message was with deprecated code, check out this if you still want to solve

import 'package:image/image.dart' as ImagePackage;

class UploadProvider {

  /// Calls `ImagePackage.decodeImage()` to identify the format of the image and use the appropriate decoder.
  /// Then, calls `ImagePackage.copyResize()` to resize the image and throws it on the `sendPort`.
  static void decodeAndCopyResize(ResizedImageMessage resizedImageMessage) {

    ImagePackage.Image resizedImage;
    
    
    ImagePackage.Image _image = ImagePackage.decodeImage(resizedImageMessage.file.readAsBytesSync());

    if (resizedImageMessage.newWidth != null && resizedImageMessage.newHeight == null) {
      resizedImage = ImagePackage.copyResize(_image, width: resizedImageMessage.newWidth);
    } 
    else if (resizedImageMessage.newWidth != null && resizedImageMessage.newHeight != null) {
      resizedImage = ImagePackage.copyResize(_image, width: resizedImageMessage.newWidth, height: resizedImageMessage.newHeight);
    }
    else if (resizedImageMessage.newWidth == null && resizedImageMessage.newHeight != null) {
      resizedImage = ImagePackage.copyResize(_image, width: _image.width, height: resizedImageMessage.newHeight);
    }
    else if (resizedImageMessage.newWidth == null && resizedImageMessage.newHeight == null) {
      resizedImage = ImagePackage.copyResize(_image, width: _image.width);
    }

    resizedImageMessage.sendPort.send(resizedImage);
  }

  /// Available types are `thumbnail`, `medium`, `large` and encodeTypes are `jpg`, `gif`. `png`.
  Future<File> compressImageFile(File file, String tempDirPath, {String sizeType = 'medium', String encodeType = 'jpg'}) async {

    if (sizeType == 'thumbnail') {
      ReceivePort receivePort = ReceivePort();
      await Isolate.spawn(decodeAndCopyResize, ResizedImageMessage(receivePort.sendPort, file, newWidth: 120));
      ImagePackage.Image _imageResizedToMedium = await receivePort.first;

      switch(encodeType) {
        case 'jpg': return File('$tempDirPath/img_thumbnail_${HelperProvider.suffixDateString()}_${HelperProvider.randomNumber()}.jpg')
          ..writeAsBytesSync(ImagePackage.encodeJpg(_imageResizedToMedium));
        case 'gif': return File('$tempDirPath/img_thumbnail_${HelperProvider.suffixDateString()}_${HelperProvider.randomNumber()}.gif')
          ..writeAsBytesSync(ImagePackage.encodeGif(_imageResizedToMedium));
        case 'png': return File('$tempDirPath/img_thumbnail_${HelperProvider.suffixDateString()}_${HelperProvider.randomNumber()}.png')
          ..writeAsBytesSync(ImagePackage.encodePng(_imageResizedToMedium));
      }
    }

    else if (sizeType == 'medium') {
      ReceivePort receivePort = ReceivePort();
      await Isolate.spawn(decodeAndCopyResize, ResizedImageMessage(receivePort.sendPort, file, newWidth: 600));
      ImagePackage.Image _imageResizedToMedium = await receivePort.first;

      switch(encodeType) {
        case 'jpg': return File('$tempDirPath/img_medium_${HelperProvider.suffixDateString()}_${HelperProvider.randomNumber()}.jpg')
          ..writeAsBytesSync(ImagePackage.encodeJpg(_imageResizedToMedium));
        case 'gif': return File('$tempDirPath/img_medium_${HelperProvider.suffixDateString()}_${HelperProvider.randomNumber()}.gif')
          ..writeAsBytesSync(ImagePackage.encodeGif(_imageResizedToMedium));
        case 'png': return File('$tempDirPath/img_medium_${HelperProvider.suffixDateString()}_${HelperProvider.randomNumber()}.png')
          ..writeAsBytesSync(ImagePackage.encodePng(_imageResizedToMedium));
      }
    }

    else if (sizeType == 'large') {
      ReceivePort receivePort = ReceivePort();
      await Isolate.spawn(decodeAndCopyResize, ResizedImageMessage(receivePort.sendPort, file));
      ImagePackage.Image _imageResizedToMedium = await receivePort.first;

      switch(encodeType) {
        case 'jpg': return File('$tempDirPath/img_large_${HelperProvider.suffixDateString()}_${HelperProvider.randomNumber()}.jpg')
          ..writeAsBytesSync(ImagePackage.encodeJpg(_imageResizedToMedium));
        case 'gif': return File('$tempDirPath/img_large_${HelperProvider.suffixDateString()}_${HelperProvider.randomNumber()}.gif')
          ..writeAsBytesSync(ImagePackage.encodeGif(_imageResizedToMedium));
        case 'png': return File('$tempDirPath/img_large_${HelperProvider.suffixDateString()}_${HelperProvider.randomNumber()}.png')
          ..writeAsBytesSync(ImagePackage.encodePng(_imageResizedToMedium));
      }
    }

    return File('');
  }

  /// Generates an unique Id to use on the name of the file, upload it 
  /// to the `FirebaseStorage` and then returns the `downloadUrl`.
  Future<String> uploadImageFile(File file, {String sizeType = 'medium', String encodeType = 'jpg'}) async {
   
    StorageReference _storageReference; 
    dynamic _uuid = Uuid().v1();
    
    if (sizeType == 'medium') {
      switch(encodeType) {
        case 'jpg': _storageReference = FirebaseStorage.instance.ref().child("post_$_uuid.jpg"); break;
        case 'gif': _storageReference = FirebaseStorage.instance.ref().child("post_$_uuid.gif"); break;
        case 'png': _storageReference = FirebaseStorage.instance.ref().child("post_$_uuid.png"); break;
      }
    }
      
    StorageUploadTask _uploadTask = _storageReference.putFile(file);

    String _downloadUrl = await (await _uploadTask.onComplete).ref.getDownloadURL();
    return _downloadUrl;
  }

  /// Generates an unique Id to use on the name of the file, upload it 
  /// to the `FirebaseStorage` and then returns the `downloadUrl`.
  Future<String> uploadVideoFile(File file) async {
    dynamic _uuid = Uuid().v1();
    StorageUploadTask _uploadTask = FirebaseStorage.instance.ref().child("post_$_uuid.mp4").putFile(file);
    return await (await _uploadTask.onComplete).ref.getDownloadURL();
  }
}

This was fixed in #76 (line) as ImagePicker was updated to support built in compression