diff --git a/lib/fingerprints/downscale.cpp b/lib/fingerprints/downscale.cpp index 360ac49..ea98dad 100644 --- a/lib/fingerprints/downscale.cpp +++ b/lib/fingerprints/downscale.cpp @@ -1,11 +1,39 @@ #include "downscale.hpp" #include + +extern "C" { +#include +#include +} + #include +#include + +static raw_rgb_image downscale_step(AVFrame const * frame, int factor) { + raw_rgb_image image(frame->width / factor, frame->height / factor); + + auto context = sws_getContext(frame->width, frame->height, static_cast(frame->format), image.width(), image.height(), image.format(), 0, nullptr, nullptr, nullptr); + if(!context) throw std::runtime_error("boem sws context"); + sws_scale (context, {frame->data}, {frame->linesize}, 0, frame->height, {image.frame->data}, {image.frame->linesize}); + sws_freeContext(context); + + return image; +} + +static raw_rgb_image downscale_to(const av::frame &frame, int w, int h){ + // ffmpeg doesnt let us downscale all the way to 5 at once :(, so we do a loop + raw_rgb_image image; + auto new_frame = frame.get(); + while(new_frame->width > 8*w && new_frame->height > 8*h){ + image = downscale_step(new_frame, 4); + new_frame = image.frame.get(); + } + return to_raw_rgb_image(image.frame, w, h); +} -downscale downscale::pre_calculate(const av::frame& frame){ - // ffmpeg doesnt let us downscale all the way to 5 at once :( - auto const image = to_raw_rgb_image(frame, 5, 5); +downscale downscale::pre_calculate(av::frame const & frame){ + auto const image = downscale_to(crop_to_square(frame), 5, 5); downscale ret; ret.data.assign(image.data.size(), 0); @@ -19,7 +47,7 @@ downscale downscale::calculate(const av::frame& frame){ return pre_calculate(frame); } -double square(double x){ +static double square(double x){ return x*x; } diff --git a/lib/image_io.cpp b/lib/image_io.cpp index be67b95..e79aac0 100644 --- a/lib/image_io.cpp +++ b/lib/image_io.cpp @@ -15,6 +15,11 @@ extern "C" { #include +raw_rgb_image::raw_rgb_image() +: data() +, frame(nullptr, [](auto x){ av_frame_free(&x); }) +{} + raw_rgb_image::raw_rgb_image(int W, int H) : data(make_u(avpicture_get_size(AV_PIX_FMT_RGB24, W, H))) , frame(av::frame_alloc()) diff --git a/lib/image_io.hpp b/lib/image_io.hpp index bf47609..ba58167 100644 --- a/lib/image_io.hpp +++ b/lib/image_io.hpp @@ -13,6 +13,7 @@ struct raw_rgb_image { std::vector> data; av::frame frame; + raw_rgb_image(); raw_rgb_image(int W, int H); int width() const; diff --git a/src/main.cpp b/src/main.cpp index 939d3f3..11c58d1 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -28,10 +28,10 @@ using namespace std; namespace fs = boost::filesystem; namespace ar = boost::archive; -using Database = image_database; +using Database = image_database; using Mozaic = map, string>; -Database read_database(string const & database_directory){ +static Database read_database(string const & database_directory){ Database db; auto const database_file = database_directory + ".db"; @@ -60,10 +60,10 @@ Database read_database(string const & database_directory){ return db; } -Mozaic create_mozaic(Database const & db, string const & filename, int h_tiles, int v_tiles){ +static Mozaic create_mozaic(Database const & db, string const & filename, int h_tiles, int v_tiles){ Mozaic mozaic; - apply_to_tiles("image.jpg", h_tiles, v_tiles, [&](int c, int r, av::frame const & frame){ + apply_to_tiles(filename, h_tiles, v_tiles, [&](int c, int r, av::frame const & frame){ auto const index = db.nearest_image(frame); cout << colors::red("tile ") << c << ", " << r << ": " << db.filename(index) << endl; mozaic[make_pair(c, r)] = db.filename(index); @@ -72,7 +72,7 @@ Mozaic create_mozaic(Database const & db, string const & filename, int h_tiles, return mozaic; } -void save_mozaic(Mozaic const & mozaic, string filename, int h_tiles, int v_tiles){ +static void save_mozaic(Mozaic const & mozaic, string filename, int h_tiles, int v_tiles){ auto const pix_fmt = AV_PIX_FMT_YUVJ444P; auto const codec_id= AV_CODEC_ID_MJPEG;