add bounding box

This commit is contained in:
Fabien Freling 2022-02-12 00:28:54 +01:00
parent 2e24f0314b
commit 7c383dc245
12 changed files with 153 additions and 4 deletions

View file

@ -7,6 +7,11 @@ The subject is available here: [Test Algo](./test_algo.pdf)
## Notes ## Notes
### Question 1 ### Question 1
This is a packing problem, as described on [Wikipedia][1].
Since this is NP-hard, we know the "exact" solution might be unreachable but we
could find a solution that is good enough for our needs.
### Question 2 ### Question 2
### Question 3 ### Question 3
@ -30,3 +35,7 @@ I use 2 external libraries for better visualization:
I don't rely on them for the algorithm implementation and the core of the I don't rely on them for the algorithm implementation and the core of the
exercise doesn't rely on external libraries. exercise doesn't rely on external libraries.
## References
[1]: https://en.wikipedia.org/wiki/Packing_problems#Packing_of_rectangles

View file

@ -6,7 +6,7 @@ build:
tup tup
run: build run: build
{{exe}} {{exe}} lenna.png 0 0 0 0
generate-build: generate-build:
git clean -xf src/ git clean -xf src/

BIN
lenna.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 463 KiB

View file

@ -1,9 +1,9 @@
CPPFLAGS_ = -Wall -Werror -std=c++17 -fcolor-diagnostics -g -O1 CPPFLAGS_ = -Wall -Werror -std=c++17 -fcolor-diagnostics -g -O1 -I./3rd-party/stb
CPPFLAGS_ASAN = $(CPPFLAGS_) -fsanitize=address -fno-omit-frame-pointer CPPFLAGS_ASAN = $(CPPFLAGS_) -fsanitize=address -fno-omit-frame-pointer
CPPFLAGS_THREAD = $(CPPFLAGS_) -fsanitize=thread CPPFLAGS_THREAD = $(CPPFLAGS_) -fsanitize=thread
CPPFLAGS_MEM = $(CPPFLAGS_) -fsanitize=memory -fno-omit-frame-pointer CPPFLAGS_MEM = $(CPPFLAGS_) -fsanitize=memory -fno-omit-frame-pointer
CPPFLAGS_UB = $(CPPFLAGS_) -fsanitize=undefined CPPFLAGS_UB = $(CPPFLAGS_) -fsanitize=undefined
CPPFLAGS = $(CPPFLAGS_) CPPFLAGS = $(CPPFLAGS_)
: foreach *.cpp |> clang++ -c %f -o %o $(CPPFLAGS) |> %B.o {objs} : foreach *.cpp |> ^ CXX %f^ clang++ -c %f -o %o $(CPPFLAGS) |> %B.o {objs}
: {objs} |> clang++ %f -o %o $(CPPFLAGS) -lpthread |> ../packing : {objs} |> ^ LINK %o^ clang++ %f -o %o $(CPPFLAGS) -lpthread |> ../packing

10
src/bounding_box.h Normal file
View file

@ -0,0 +1,10 @@
#pragma once
#include <cstdint>
struct BoundingBox {
uint32_t left;
uint32_t top;
uint32_t right;
uint32_t bottom;
};

35
src/frame.cpp Normal file
View file

@ -0,0 +1,35 @@
#include "frame.h"
#include <cstring>
Frame::Frame(uint32_t width, uint32_t height) : width(width), height(height) {
data = new Pixel[width * height];
}
Frame::Frame(const Frame& other) : Frame(other.width, other.height) {
std::memcpy(data, other.data, width * height);
}
Frame& Frame::operator=(const Frame& other) {
width = other.width;
height = other.height;
delete[] data;
data = new Pixel[width * height];
std::memcpy(data, other.data, width * height);
return *this;
}
Frame::Frame(Frame&& other) {
width = other.width;
height = other.height;
data = other.data;
other.data = nullptr;
}
Frame::~Frame() {
delete[] data;
}
void Frame::fill(uint8_t p) {
std::memset(data, p, width * height * sizeof(Pixel));
}

23
src/frame.h Normal file
View file

@ -0,0 +1,23 @@
#pragma once
#include <cstdint>
struct Pixel {
uint32_t r;
uint32_t g;
uint32_t b;
};
struct Frame {
uint32_t width;
uint32_t height;
Pixel* data;
Frame(uint32_t width, uint32_t height);
Frame(const Frame& other);
Frame& operator=(const Frame& other);
Frame(Frame&& other);
~Frame();
void fill(uint8_t p);
};

View file

@ -1,5 +1,10 @@
#include <filesystem> #include <filesystem>
#include <iostream> #include <iostream>
#include <vector>
#include "bounding_box.h"
#include "pack.h"
#include "png.h"
namespace fs = std::filesystem; namespace fs = std::filesystem;
@ -20,5 +25,25 @@ int main(int argc, const char* argv[]) {
return 1; return 1;
} }
const std::optional<Frame> in_frame = load_png(input);
if (!in_frame) {
std::cerr << "Cannot load file " << input << "\n";
return 1;
}
int i = 2;
std::vector<BoundingBox> bboxes;
bboxes.reserve((argc - 2) / 4);
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(BoundingBox({x1, y1, x2, y2}));
i += 4;
}
Frame regions = pack(*in_frame, bboxes);
return 0; return 0;
} }

6
src/pack.cpp Normal file
View file

@ -0,0 +1,6 @@
#include "pack.h"
Frame pack(const Frame& in_frame, const std::vector<BoundingBox>& bboxes) {
// TODO
return Frame(1, 1);
}

8
src/pack.h Normal file
View file

@ -0,0 +1,8 @@
#pragma once
#include <vector>
#include "bounding_box.h"
#include "frame.h"
Frame pack(const Frame& in_frame, const std::vector<BoundingBox>& bboxes);

25
src/png.cpp Normal file
View file

@ -0,0 +1,25 @@
#include "png.h"
#include <cstring>
#include <iostream>
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"
std::optional<Frame> load_png(const std::filesystem::path& in) {
int x = 0;
int y = 0;
int channels = 0;
const int desired_channels = 3;
unsigned char* data =
stbi_load(in.c_str(), &x, &y, &channels, desired_channels);
if (data == NULL) {
return {};
}
Frame f(x, y);
std::memcpy(f.data, data, x * y * desired_channels);
stbi_image_free(data);
return f;
}

8
src/png.h Normal file
View file

@ -0,0 +1,8 @@
#pragma once
#include <filesystem>
#include <optional>
#include "frame.h"
std::optional<Frame> load_png(const std::filesystem::path& in);