1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
|
#include <SFML/Graphics.hpp>
#include <thread>
#include <mutex>
#include <deque>
int main() {
const int fps = 24;
sf::Texture texture;
if(!texture.loadFromFile("flag.png"))
return 1;
texture.setSmooth(true);
sf::Vector2u window_size = texture.getSize();
sf::RenderWindow window(sf::VideoMode(window_size.x, window_size.y), "SFML works!", 0);
window.setVerticalSyncEnabled(false);
window.setFramerateLimit(0);
sf::Shader shader;
if(!shader.loadFromFile("flag.glsl", sf::Shader::Type::Fragment))
return 1;
shader.setUniform("texture", texture);
sf::Vertex vertex[4];
vertex[0] = sf::Vertex(sf::Vector2f(0.0f, 0.0f), sf::Color::White, sf::Vector2f(0.0f, 0.0f));
vertex[1] = sf::Vertex(sf::Vector2f(window_size.x, 0.0f), sf::Color::White, sf::Vector2f(1.0f, 0.0f));
vertex[2] = sf::Vertex(sf::Vector2f(window_size.x, window_size.y), sf::Color::White, sf::Vector2f(1.0f, 1.0f));
vertex[3] = sf::Vertex(sf::Vector2f(0.0f, window_size.y), sf::Color::White, sf::Vector2f(0.0f, 1.0f));
sf::Texture texture_output;
texture_output.create(texture.getSize().x, texture.getSize().y);
int flag_start_x = texture.getSize().x*0.2;
int flag_start_y = texture.getSize().y*0.2;
int flag_width = texture.getSize().x*0.6;
int flag_height = texture.getSize().y*0.6;
system("rm -rf frames/*; mkdir frames");
std::deque<sf::Image> pending_frames;
std::mutex images_lock;
bool running = true;
std::thread work_thread([&images_lock, &running, &pending_frames]() mutable {
size_t frame_index = 0;
while(true) {
images_lock.lock();
if(!pending_frames.empty()) {
sf::Image image = std::move(pending_frames.front());
pending_frames.pop_front();
images_lock.unlock();
image.saveToFile("frames/" + std::to_string(frame_index) + ".png");
++frame_index;
} else {
bool is_kill = !running;
images_lock.unlock();
if(is_kill)
break;
}
}
});
sf::Image output_image;
output_image.create(flag_width, flag_height, sf::Color::Transparent);
const float playtime_sec = 2.0f;
const float frame_time = 1000.0 / (double)fps / 1000.0;
double elapsed_frame_time = 0.0;
while (window.isOpen()) {
sf::Event event;
while (window.pollEvent(event)) {
if (event.type == sf::Event::Closed)
window.close();
}
shader.setUniform("iTime", (float)elapsed_frame_time);
window.clear(sf::Color::Transparent);
window.draw(vertex, 4, sf::PrimitiveType::Quads, &shader);
window.display();
texture_output.update(window);
sf::Image image = texture_output.copyToImage();
output_image.copy(image, 0, 0, sf::IntRect(flag_start_x, flag_start_y, flag_width, flag_height), false);
std::lock_guard<std::mutex> lock(images_lock);
pending_frames.push_back(output_image);
elapsed_frame_time += frame_time;
if(elapsed_frame_time >= playtime_sec)
break;
}
running = false;
work_thread.join();
system("ffmpeg -i \"frames/%d.png\" -framerate 24 -filter_complex \"fps=24,split=2[palette_in][gif];[palette_in]palettegen[palette_out];[gif]fifo[gif_fifo]; [gif_fifo][palette_out]paletteuse\" -y output.gif");
system("rm -rf frames");
return 0;
}
|