Is their any way to convert .jpeg images to .gif in flutter?

873

You can use the image package to created animated GIFs from multiple images.

First add it as a dependency:

dependencies:
  image: ^3.0.2

Then to you can make a function to generate an animated GIF from multiple images:

List<int>? generateGIF(Iterable<Image> images) {
  final Animation animation = Animation();
  for(Image image in images) {
    animation.addFrame(image);
  }
  return encodeGifAnimation(animation);
}

To use this function with multiple images that are in files from the camera package in the form of XFiles, you have to decode the images for each of those files and pass it to this function. The following code assumes you know that these are JPEG images:

List<XFile> imageFiles = ...;

final JpegDecoder decoder = JpegDecoder();
final List<Image> images = [];
for(var imgFile in imageFiles) {
  Uint8List data = await imgFile.readAsBytes();
  images.add(decoder.decodeImage(data));
}

List<int>? gifData = generateGIF(images);
Share:
873
John Park
Author by

John Park

Updated on December 29, 2022

Comments

  • John Park
    John Park over 1 year

    Like my title, is there anyway to convert images to a video in flutter? (It doesn't have to be .gif necessarily)

    To be more specific, I am using Google Firebase as my storage cloud server to upload pictures taken by camera plugin of flutter.

    I want to convert my images to a video so that it looks like a time-lapse video. Any advice would be nice.

    ===============================

    the pictures are taken by camera plugin which uses camera.dart, and it is stored it firebase storage like this:

    onCapture(context) async {
    try {
      final p = await getTemporaryDirectory();
      var now = DateTime.now();
      var formattedDate = DateFormat('yy-MM-dd HH:mm:ss').format(now);
      final path = '${p.path}/$now.png';
      await cameraController.takePicture(path).then((value) {
        print('here');
        Navigator.push(
            context,
            MaterialPageRoute(
                builder: (context) => PreviewScreen(
                      imgPath: path,
                      fileName: '$formattedDate.png',
                      pickedTime: '$formattedDate',
                    )));
      });
    } catch (e) {
      showCameraException(e);
     }
    }
    

    ========================================

    edit : Before constructing gif, i am having trouble downloading an image from firebase and putting this image on the canvas. I think I can use your code to make a gif once I do this.

    import 'dart:io';
    import 'dart:isolate';
    import 'package:flutter/material.dart';
    import 'package:image/image.dart' as IMG;
    import 'package:path/path.dart';
    import 'package:path_provider/path_provider.dart';
    import 'package:firebase_storage/firebase_storage.dart' as firebase_storage;
    import 'package:firebase_core/firebase_core.dart' as firebase_core;
    import 'package:provider/provider.dart';
    import 'package:weighit/models/user_info.dart';
    
    class ToGif extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: Text('Timelapse Video'),
          ),
          body: Container(
            child: Thumbnail(),
          ),
        );
      }
    }
    
    class Thumbnail extends StatefulWidget {
      const Thumbnail({Key key}) : super(key: key);
      @override
      _ThumbnailState createState() => _ThumbnailState();
    }
    
    class _ThumbnailState extends State<Thumbnail> {
      List<int> imgBytes;
      Isolate isolate;
      File image;
    
      @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();
        isolate = await Isolate.spawn(_isolateEntry, receivePort.sendPort);
    
        receivePort.listen((dynamic data) {
          if (data is SendPort) {
            if (mounted) {
              data.send({
                'path': image.path,
                'size': Size(500, 500),
              });
            }
          } else {
            if (mounted) {
              setState(() {
                imgBytes = data;
              });
            }
          }
        });
      }
    
      @override
      void dispose() {
        if (isolate != null) {
          isolate.kill();
        }
        super.dispose();
      }
    
      // Download on DocumnetDirectory, not temporary directory https://flutter-ko.dev/docs/cookbook/persistence/reading-writing-files
      Future<void> downloadFileExample() async {
        final appDocDir = await getApplicationDocumentsDirectory();
        image = File('${appDocDir.path}/download-logo.png');
    
        try {
          await firebase_storage.FirebaseStorage.instance
              // can not find proper reference path...
              .ref('gs://weighit-f506b.appspot.com/guny/21-04-26 10:56:21.png')
              .writeToFile(image);
        } on firebase_core.FirebaseException catch (e) {
          print('couldnt find the reference');
        }
      }
    
      @override
      Widget build(BuildContext context) {
        final _user = Provider.of<TheUser>(context);
        return FutureBuilder(
          future: downloadFileExample(),
          builder: (context, snapshot) {
            //해당 부분은 data를 아직 받아 오지 못했을때 실행되는 부분을 의미한다.
            if (snapshot.hasData == false) {
              return Center(child: CircularProgressIndicator());
            }
            //error가 발생하게 될 경우 반환하게 되는 부분
            else if (snapshot.hasError) {
              return Padding(
                padding: const EdgeInsets.all(8.0),
                child: Text(
                  'Error: ${snapshot.error}',
                  style: TextStyle(fontSize: 15),
                ),
              );
            } else {
              return SizedBox(
                height: 500,
                width: 500,
                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,
                          ),
                        ),
                      ),
              );
            }
          },
        );
      }
    }
    
    • Rachel Gallen
      Rachel Gallen about 3 years
      please add a code sample of what you have tried so far
    • John Park
      John Park about 3 years
      @RachelGallen sorry for the late reply, it was my mid-term exam week so I didn't have time to check! I will show my code, but I don't have any code that converts images to .gif since I don't have any clue :(
  • John Park
    John Park about 3 years
    Thank you for giving me an idea to implement timelapse video. But I tried your code, and it didn't work out well :( I am quite new to flutter, so I couldn't sought this out by myself
  • John Park
    John Park about 3 years
    firstly, as I import images package to my dart file, it caused an 'ambiguous import' error on declaring Image type. Declaring Animation class was also impossible due to ambiguous error. Also, Animation class is abstract class that couldn't be used... I tried my best to fix these errors but I couldn't help it
  • Christopher Moore
    Christopher Moore about 3 years
    @JohnPark You need to import the library somewhere. Your IDE should be able to suggest the correct import, but here it is anyways import 'package:image/image.dart';
  • John Park
    John Park about 3 years
    Thank you! i did that, and the problem was that there is another Image class included in material.dart. I fixed that problem by using 'as' prefix like 'import 'package:image/image.dart' as img;'
  • John Park
    John Park about 3 years
    I have a new problem now... how do i get a path for image files??
  • Christopher Moore
    Christopher Moore about 3 years
    @JohnPark What do you have so far? If you're getting it directly from the camera then you should be able to figure it out from the second block of code. If you're getting it from firebase storage, you need to download it as a Uint8List and put it into the second block of code in my answer.
  • John Park
    John Park about 3 years
    Before generating gif, I am having trouble downloading an image from firebase and putting this on the canvas. I posted my code above :) I really appreciate your help
  • Christopher Moore
    Christopher Moore about 3 years
    @JohnPark Please do not add additional information as answers. Please edit the code into the question and reduce it down as much as possible. You have code to download some firebase images. Make an attempt at downloading the data yourself and if you have problems, be as specific as possible.
  • John Park
    John Park about 3 years
    sorry that I am also new to stackoverflow and I was lacking of basic manners.. I will do my best to find the solutions by myself. Beside that, your answer helped a lot!