#include #include #include #include static constexpr size_t s_window_width = 400; static constexpr size_t s_window_height = 400; static constexpr float s_scale_factor = 0.9f; static void run(LibImage::Image& image, LibGUI::Window& window) { int32_t xoff = static_cast(window.width() - image.width()) / 2; int32_t yoff = static_cast(window.height() - image.height()) / 2; float scale = 1.0f; bool mouse_pressed = false; int32_t mouse_x = 0; int32_t mouse_y = 0; bool should_close = false; bool should_display = false; bool linear = false; const auto display_image = [&]() -> void { window.texture().fill(0xFFFFFF); for (int32_t winy = 0; winy < static_cast(window.height()); winy++) { for (int32_t winx = 0; winx < static_cast(window.width()); winx++) { LibImage::Image::Color color; if (!linear) { const int32_t imgx = BAN::Math::round((winx - xoff) / scale); const int32_t imgy = BAN::Math::round((winy - yoff) / scale); if (imgx < 0 || imgx >= static_cast(image.width())) continue; if (imgy < 0 || imgy >= static_cast(image.height())) continue; color = image.get_color(imgx, imgy); } else { const float fimgx = (winx - xoff) / scale; const float fimgy = (winy - yoff) / scale; if (fimgx + 0.5f < 0 || fimgx + 0.5f >= image.width()) continue; if (fimgy + 0.5f < 0 || fimgy + 0.5f >= image.height()) continue; const int32_t imgl = BAN::Math::clamp(fimgx, 0, image.width() - 1); const int32_t imgr = BAN::Math::clamp(imgl + 1, 0, image.width() - 1); const int32_t imgt = BAN::Math::clamp(fimgy, 0, image.height() - 1); const int32_t imgb = BAN::Math::clamp(imgt + 1, 0, image.height() - 1); const auto tl = image.get_color(imgl, imgt); const auto tr = image.get_color(imgr, imgt); const auto bl = image.get_color(imgl, imgb); const auto br = image.get_color(imgr, imgb); const float weightx = fimgx - BAN::Math::floor(fimgx); const float weighty = fimgy - BAN::Math::floor(fimgy); color = LibImage::Image::Color::average( LibImage::Image::Color::average(tl, tr, weightx), LibImage::Image::Color::average(bl, br, weightx), weighty ); } window.texture().set_pixel(winx, winy, color.as_argb()); } } window.invalidate(); }; window.set_close_window_event_callback([&] { should_close = true; }); window.set_resize_window_event_callback([&] { should_display = true; }); window.set_mouse_button_event_callback([&](auto event) { if (event.button != LibInput::MouseButton::Left) return; mouse_pressed = event.pressed; mouse_x = event.x; mouse_y = event.y; }); window.set_mouse_move_event_callback([&](auto event) { if (mouse_pressed) { xoff += event.x - mouse_x; yoff += event.y - mouse_y; should_display = true; } mouse_x = event.x; mouse_y = event.y; }); window.set_mouse_scroll_event_callback([&](auto event) { const float new_scale = scale * BAN::Math::pow(s_scale_factor, -event.scroll); xoff = mouse_x - (mouse_x - xoff) / scale * new_scale; yoff = mouse_y - (mouse_y - yoff) / scale * new_scale; scale = new_scale; should_display = true; }); window.set_key_event_callback([&](LibGUI::EventPacket::KeyEvent::event_t event) { if (!event.pressed()) return; switch (event.key) { case LibInput::Key::Space: linear = !linear; should_display = true; break; default: break; } }); display_image(); auto attributes = window.get_attributes(); attributes.shown = true; window.set_attributes(attributes); while (!should_close) { window.wait_events(); window.poll_events(); if (should_display) display_image(); should_display = false; } } int main(int argc, char** argv) { if (argc != 2) { fprintf(stderr, "usage: %s image_file\n", argv[0]); return 1; } auto image_or_error = LibImage::Image::load_from_file(argv[1]); if (image_or_error.is_error()) { fprintf(stderr, "Failed to load '%s': %s\n", argv[1], image_or_error.error().get_message()); return 1; } auto image = image_or_error.release_value(); auto window_attributes = LibGUI::Window::default_attributes; window_attributes.resizable = true; window_attributes.shown = false; auto window_or_error = LibGUI::Window::create(s_window_width, s_window_height, argv[1], window_attributes); if (window_or_error.is_error()) { fprintf(stderr, "Failed to create an window: %s\n", window_or_error.error().get_message()); return 1; } auto window = window_or_error.release_value(); run(*image, *window); return 0; }