他们有办法将 .jpeg 图像转换为 .gif 吗?

问题描述 投票:0回答:1

有办法将图像转换为视频吗? (不一定是.gif)

更具体地说,我使用Google Firebase作为我的存储云服务器来上传Flutter的相机插件拍摄的照片。

我想将图像转换为视频,使其看起来像延时视频。


照片是由使用camera.dart的相机插件拍摄的,并存储在Firebase存储中,如下所示:

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);
 }
}

编辑: 在构建 gif 之前,我无法从 firebase 下载图像并将该图像放在画布上。我想一旦我这样做了,我就可以使用你的代码来制作 gif 了。

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,
                      ),
                    ),
                  ),
          );
        }
      },
    );
  }
}
flutter dart video jpeg
1个回答
8
投票

您可以使用

image
包从多个图像创建动画 GIF。

首先将其添加为依赖项:

dependencies:
  image: ^3.0.2

然后你可以创建一个函数来从多个图像生成动画 GIF:

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

要将此函数与

camera
包中以
XFile
形式存在的多个图像一起使用,您必须解码每个文件的图像并将其传递给此函数。以下代码假设您知道这些是 JPEG 图像:

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);
© www.soinside.com 2019 - 2024. All rights reserved.