How can I read (from disk) and resize an image, in Flutter/Dart

前端 未结 8 650
爱一瞬间的悲伤
爱一瞬间的悲伤 2020-12-09 08:53

In Flutter/Dart, how can I perform the following 3 steps:

  1. Read an image from disk,
  2. Read its original dimensions (width and height),
  3. Resiz
8条回答
  •  眼角桃花
    2020-12-09 09:13

    Here's an example Thumbnail widget which does this on the flight

    It uses Isolate to offload CPU-intensive work to background thread and have UI thread jank-free

    import 'dart:io';
    import 'dart:isolate';
    import 'package:flutter/material.dart';
    import 'package:image/image.dart' as IMG;
    import 'package:path/path.dart';
    
    class Thumbnail extends StatefulWidget {
      final Size size;
      final File image;
    
      const Thumbnail({Key key, this.size, this.image}) : super(key: key);
      @override
      _ThumbnailState createState() => _ThumbnailState();
    }
    
    class _ThumbnailState extends State {
      List imgBytes;
      Isolate isolate;
    
      @override
      void initState() {
        _asyncInit();
    
        super.initState();
      }
    
      static _isolateEntry(dynamic d) async {
        final ReceivePort receivePort = ReceivePort();
        d.send(receivePort.sendPort);
    
        final config = await receivePort.first;
    
        print(config);
    
        final file = File(config['path']);
        final bytes = await file.readAsBytes();
    
        IMG.Image image = IMG.decodeImage(bytes);
        IMG.Image thumbnail = IMG.copyResize(
          image,
          width: config['size'].width.toInt(),
        );
    
        d.send(IMG.encodeNamedImage(thumbnail, basename(config['path'])));
      }
    
      _asyncInit() async {
        final ReceivePort receivePort = ReceivePort();
        isolate = await Isolate.spawn(_isolateEntry, receivePort.sendPort);
    
        receivePort.listen((dynamic data) {
          if (data is SendPort) {
            if (mounted) {
              data.send({
                'path': widget.image.path,
                'size': widget.size,
              });
            }
          } else {
            if (mounted) {
              setState(() {
                imgBytes = data;
              });
            }
          }
        });
      }
    
      @override
      void dispose() {
        if (isolate != null) {
          isolate.kill();
        }
        super.dispose();
      }
    
      @override
      Widget build(BuildContext context) {
        return SizedBox(
          height: widget.size.height,
          width: widget.size.width,
          child: imgBytes != null
              ? Image.memory(
                  imgBytes,
                  fit: BoxFit.cover,
                )
              : Container(
                  decoration: BoxDecoration(
                    gradient: LinearGradient(
                      colors: [Colors.grey[100], Colors.grey[300]],
                      begin: Alignment.centerLeft,
                      end: Alignment.centerRight,
                    ),
                  ),
                ),
        );
      }
    }
    

提交回复
热议问题