I am trying to have folder of images either converted to a video format I can play and edit frames of or just iterate through the folder and display them. I am using VS, C#, WPF and .NET 4.7.2.
The folder also has a .txt document named "files.txt" that has all of the files in the folder line by line.
Example (Separated by lines, not spaces)-
" frame_000000.jpg frame_000001.jpg frame_000002.jpg frame_000003.jpg frame_000004.jpg frame_000005.jpg ... "
When I drop the folder into the application it begins running.
Here is what I have so far.
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();
}
}
}
}
}
}
First of all I had to convert all the JPG files to PNG outside of the code. Second it only shows the last image in the folder.
I can't figure out how to get the JPG into a video format or display them at 25 FPS. Any help would be greatly appreciated!
CodePudding user response:
Disclaimer: Here is a solution to the questions that you asked that works. I've tested it. However, it's not ideal and I don't recommend it, because this code is dependent on how fast your system is able to perform asynchronous context switching.
- This code works on JPG, PNG, and a few other formats. I'm not sure why you needed to convert all your JPG files to PNG.
- The reason why your code only showed the last image in the folder is because you were running all your code synchronously on the UI thread, so it wasn't able to update the UI until your entire "for" loop was done. You need to break up the UI thread by using the async/await pattern. Look it up if you're not familiar with this way of coding.
The code:
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);
}
}
}
}
}
And the 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>
Lastly, the code assumes your "files.txt" is listed without the directory name, only the file names. Like this:
file1.jpg
file2.PNG
file3.bmp
file4.jpg
...
CodePudding user response:
You may use ffmpeg and the techniques described in this SuperUser post to turn your file frames into a movie
ffmpeg -framerate 25 -i frame_%08d.jpg out.mp4
If you're on Windows you might have to double up the % sign