#include #include #include #include int main() { const int fps = 24; const float playtime_sec = 1.78f; 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), "flag-maker", 0, sf::ContextSettings(0, 0, 4)); 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 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 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 lock(images_lock); pending_frames.push_back(output_image); elapsed_frame_time += frame_time; if(elapsed_frame_time >= playtime_sec) break; } window.close(); running = false; work_thread.join(); char command[256]; snprintf(command, sizeof(command), "ffmpeg -i \"frames/%%d.png\" -framerate %d -filter_complex \"fps=%d,split=2[palette_in][gif];[palette_in]palettegen[palette_out];[gif]fifo[gif_fifo]; [gif_fifo][palette_out]paletteuse\" -y output.gif", fps, fps); system(command); system("rm -rf frames"); return 0; }