【问题标题】:How to convert all PNGs in a folder to JPG in order to make a video?如何将文件夹中的所有 PNG 转换为 JPG 以制作视频?
【发布时间】:2021-09-16 00:23:03
【问题描述】:

我正在尝试将图像文件夹转换为可以播放和编辑帧的视频格式,或者只是遍历文件夹并显示它们。我正在使用 VS、C#、WPF 和 .NET 4.7.2。

该文件夹还有一个名为“files.txt”的 .txt 文档,其中逐行包含文件夹中的所有文件。

示例(以行分隔,而不是空格)-

" frame_000000.jpg frame_000001.jpg frame_000002.jpg frame_000003.jpg frame_000004.jpg frame_000005.jpg ... "

当我将文件夹放入应用程序时,它开始运行。

这是我目前所拥有的。

using System;
using System.IO;
using System.Linq;
using System.Windows;
using System.Windows.Media.Imaging;

namespace WpfApp2
{
    public partial class MainWindow : Window
    {
        public static string filename { get; set; }
        public static string imageName { get; set; }

        public MainWindow()
        {
            InitializeComponent();
        }

        public void UpdateImage()
        {
            ImportImage.Source = new BitmapImage(new Uri(imageName));
        }

        public void FileDropStackPanel_Drop(object sender, DragEventArgs e)
        {
            if (e.Data.GetDataPresent(DataFormats.FileDrop))
            {
                string[] files = (string[])e.Data.GetData(DataFormats.FileDrop);
                filename = Path.GetFullPath(files[0]);
                GetFileName();
            }
        }

        public void GetFileName()
        {
            listFilesInDirectory(filename);
            void listFilesInDirectory(string workingDirectory)
            {
                string[] filePaths = Directory.GetFiles(workingDirectory);

                if (filePaths.Contains(filename + @"\files.txt"))
                {
                    string textFile = filename + @"\files.txt";
                    string[] lines = File.ReadAllLines(textFile);

                    for (int x = 0; x < lines.Length; x++)
                    {
                        imageName = filename + @"\" + lines[x];
                        UpdateImage();
                    }

                }
            }
        }
    }
}

首先,我必须在代码之外将所有 JPG 文件转换为 PNG。其次,它只显示文件夹中的最后一张图片。

我不知道如何将 JPG 转换为视频格式或以 25 FPS 的速度显示它们。任何帮助将不胜感激!

【问题讨论】:

  • 您说您使用外部方法将 JPG 转换为 PNG,但您的应用可以处理 JPG 文件。是哪个?
  • 创建视频是一项复杂的任务。最后我看到它是 DirectShow API 的一部分
  • 我需要它来处理 JPG 但现在它只能处理 PNG。
  • 感谢更新,我是想问为什么"文件夹里还有一个.txt文档里面有文件夹里的所有文件逐行"。你不能只是Directory.EnumerateFiles()吗?您可以创建一个名为 Inbox 或其他名称的文件夹。祝你好运! :)

标签: c# .net wpf


【解决方案1】:

免责声明:以下是您提出的问题的有效解决方案。我已经测试过了。但是,它并不理想,我不推荐它,因为此代码取决于您的系统能够执行异步上下文切换的速度。

  1. 此代码适用于 JPG、PNG 和其他一些格式。我不确定您为什么需要将所有 JPG 文件转换为 PNG。
  2. 您的代码只显示文件夹中的最后一张图像的原因是因为您在 UI 线程上同步运行所有代码,因此在完成整个“for”循环之前无法更新 UI。您需要使用 async/await 模式来分解 UI 线程。如果您不熟悉这种编码方式,请查看它。

代码:

using System;
using System.IO;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Media.Imaging;

namespace _69201085
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        public void UpdateImage(string imageName)
        {
            ImportImage.Source = new BitmapImage(new Uri(imageName));
        }

        private async Task ShowFilesInFolder(string workingDirectory)
        {
            var textFile = Path.Combine(workingDirectory, "files.txt");
            if (File.Exists(textFile))
            {
                // Parse the file, then iterate through all of the listed images at 25 FPS
                var lines = await File.ReadAllLinesAsync(textFile);
                foreach (var line in lines)
                {
                    var imageName = Path.Combine(workingDirectory, line.Trim());
                    // Check that the file exists before you try to change the image
                    if (File.Exists(imageName))
                    {
                        // Make sure that the file is one of the approved image formats
                        if (
                            Path.GetExtension(imageName).ToLower() == ".jpg" ||
                            Path.GetExtension(imageName).ToLower() == ".png" ||
                            Path.GetExtension(imageName).ToLower() == ".jpeg" ||
                            Path.GetExtension(imageName).ToLower() == ".jfif" ||
                            Path.GetExtension(imageName).ToLower() == ".gif" ||
                            Path.GetExtension(imageName).ToLower() == ".bmp"
                            )
                        {
                            // Update the image
                            UpdateImage(imageName);

                            // If you want 25 FPS, then wait 40 ms
                            await Task.Delay(40);
                        }
                    }
                }
            }
        }

        private async void Window_Drop(object sender, DragEventArgs e)
        {
            if (e.Data.GetDataPresent(DataFormats.FileDrop))
            {
                string[] files = (string[])e.Data.GetData(DataFormats.FileDrop);

                string folder = Path.GetFullPath(files[0]);
                if (!Directory.Exists(folder))
                {
                    folder = Path.GetDirectoryName(files[0]);
                }

                // Verify that the directory/folder exists
                if (Directory.Exists(folder))
                {
                    await ShowFilesInFolder(folder);
                }
            }
        }
    }
}

还有 xaml:

<Window x:Class="_69201085.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800" Drop="Window_Drop" AllowDrop="True">
    <Grid>
        <StackPanel x:Name="FileDropStackPanel">
            <Image x:Name="ImportImage" Stretch="Fill" />
        </StackPanel>
    </Grid>
</Window>

最后,代码假定您的“files.txt”没有列出目录名,只有文件名。像这样:

file1.jpg
file2.PNG
file3.bmp
file4.jpg
...

【讨论】:

  • 非常感谢!我尝试运行它,当我尝试删除 JPG 文件夹时,没有任何反应。我看到您已将图像嵌套到 StackPanel 中。这有什么好处?
  • @ChaseRatliff 抱歉,我的 Window_Drop 方法出现逻辑错误。请查看更新后的答案,然后使用 jpg 图像重试。我自己用扩展名为“.jpg”的文件对其进行了测试,它工作正常。至于 StackPanel,它没有任何用途……那只是您原始代码的产物,因此您可以完全摆脱它。
  • 是的,我想通了。 “FullFilePath”正确吗?但是我想说谢谢你,你让我对 WPF 和 C# 有了更好的理解!
  • 是的,很高兴我能帮上忙。
【解决方案2】:

您可以使用 ffmpeg 和技术described in this SuperUser post 将您的文件帧变成电影

ffmpeg -framerate 25 -i frame_%08d.jpg out.mp4

如果您使用的是 Windows,则可能需要将 % 符号加倍

【讨论】:

    猜你喜欢
    • 2019-10-27
    • 1970-01-01
    • 2019-09-22
    • 1970-01-01
    • 2017-08-08
    • 2012-12-15
    • 2015-05-09
    • 2018-11-15
    • 2014-01-25
    相关资源
    最近更新 更多