#include #include #include #include #include #include #include #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wunused-result" #define RAYGUI_IMPLEMENTATION #include #pragma clang diagnostic pop #include "bounding_box.h" #include "frame.h" #include "pack.h" #include "png.h" namespace fs = std::filesystem; struct Button { Rectangle rect; std::string text; bool hover = false; bool pressed() { hover = CheckCollisionPointRec(GetMousePosition(), rect); return hover and IsMouseButtonReleased(MOUSE_BUTTON_LEFT); }; void draw() const { DrawRectangleRec(rect, LIGHTGRAY); DrawRectangleLines(rect.x, rect.y, rect.width, rect.height, BLUE); DrawText(text.c_str(), (rect.x + rect.width / 2 - MeasureText(text.c_str(), 10) / 2), rect.y + 11, 10, DARKBLUE); }; }; void draw(const freling::BoundingBox& box, const Vector2& offset, const Color& color) { const Rectangle rect = {offset.x + box.left, offset.y + box.top, static_cast(box.right - box.left), static_cast(box.bottom - box.top)}; DrawRectangleRec(rect, ColorAlpha(color, 0.3)); DrawRectangleLinesEx(rect, 3, color); } Image image_from_frame(const Frame& frame) { Image image = {0}; const int format = PIXELFORMAT_UNCOMPRESSED_R8G8B8; const unsigned int size = GetPixelDataSize(frame.width, frame.height, format); image.data = RL_MALLOC(size); memcpy(image.data, frame.data, size); image.width = frame.width; image.height = frame.height; image.mipmaps = 1; image.format = format; return image; } int main(int argc, const char* argv[]) { if (argc < 2 or (argc - 2) % 4 != 0) { std::cerr << "Usage: " << argv[0] << " path/to/image" << " [x1 y1 x2 y2 ...]\n" << "x/y points must be grouped by 4 to define bounding boxes\n"; return 1; } const fs::path input(argv[1]); if (!fs::exists(input)) { std::cerr << "Input file " << input << " does not exist.\n"; return 1; } const std::optional in_frame = load_png(input); if (!in_frame) { std::cerr << "Cannot load file " << input << "\n"; return 1; } std::vector bboxes; bboxes.reserve((argc - 2) / 4); int i = 2; while (i < argc) { const uint32_t x1 = atoi(argv[i]); const uint32_t y1 = atoi(argv[i + 1]); const uint32_t x2 = atoi(argv[i + 2]); const uint32_t y2 = atoi(argv[i + 3]); bboxes.push_back(freling::BoundingBox({x1, y1, x2, y2})); i += 4; } const std::vector bbox_colors = {RED, GREEN, BLUE}; Vector2 win_size = {800, 450}; const int padding = 5; const Vector2 in_offset = {padding, 40}; InitWindow(win_size.x, win_size.y, "netatmo - rect packing"); SetTargetFPS(60); Image in_img = image_from_frame(*in_frame); Texture2D in_texture = LoadTextureFromImage(in_img); Image pack_img; Texture2D pack_texture; bool packed = false; win_size.x = std::max(win_size.x, in_offset.x + in_texture.width + padding); win_size.y = std::max(win_size.y, in_offset.y + in_texture.height + padding); SetWindowSize(win_size.x, win_size.y); const Vector2 b_size = {150, 30}; Button b_add_box = {{padding, padding, b_size.x, b_size.y}, "Add box"}; Button b_pack = {{padding * 2 + b_size.x, padding, b_size.x, b_size.y}, "Pack rects"}; while (!WindowShouldClose()) { BeginDrawing(); ClearBackground(RAYWHITE); // // Buttons // if (GuiButton((Rectangle){padding, padding, b_size.x, b_size.y}, "Add Box")) { bboxes.push_back(freling::BoundingBox({0, 0, 64, 64})); } if (GuiButton((Rectangle){padding * 2 + b_size.x, padding, b_size.x, b_size.y}, "Pack Rects")) { std::optional f_packed = pack(*in_frame, bboxes); if (packed) { UnloadTexture(pack_texture); UnloadImage(pack_img); } pack_img = image_from_frame(*f_packed); pack_texture = LoadTextureFromImage(pack_img); packed = true; win_size.x = std::max(win_size.x, in_offset.x + in_texture.width + padding * 2 + pack_texture.width); win_size.y = std::max( win_size.y, in_offset.y + std::max(in_texture.height, pack_texture.height) + padding); SetWindowSize(win_size.x, win_size.y); } // // Input image // DrawTexture(in_texture, in_offset.x, in_offset.y, WHITE); DrawRectangleLines(in_offset.x, in_offset.y, in_texture.width, in_texture.height, BLACK); int c = 0; for (const auto& b : bboxes) { const auto& color = bbox_colors[c % bboxes.size()]; draw(b, in_offset, color); ++c; }; // // Packed image // if (packed) { const int offset_x = in_offset.x + in_texture.width + padding; DrawTexture(pack_texture, offset_x, in_offset.y, WHITE); DrawRectangleLines(offset_x, in_offset.y, pack_texture.width, pack_texture.height, BLACK); } EndDrawing(); } // Cleanup UnloadTexture(in_texture); UnloadImage(in_img); if (packed) { UnloadTexture(pack_texture); UnloadImage(pack_img); } CloseWindow(); return 0; }