22 #include <fvutils/writers/png.h>
23 #include <utils/misc/string_conversions.h>
24 #include <utils/system/argparser.h>
26 #include <mongocxx/client.hpp>
27 #include <mongocxx/gridfs/bucket.hpp>
28 #include <mongocxx/gridfs/downloader.hpp>
30 using namespace firevision;
31 using namespace mongocxx;
33 using namespace bsoncxx;
34 using namespace bsoncxx::builder;
37 print_usage(
const char *progname)
39 printf(
"Usage: %s [-h] [-o dir] [-f] [-d database] -c collection items...\n"
40 " -h Show this help message\n"
41 " -o dir Output directory where to create PNG files\n"
42 " -f Use original filenames form database\n"
43 " -d database Database to query for images\n"
44 " -c collection Collection to query for images\n"
46 "Items are either timestamps (ms precision) or timestamp ranges in\n"
49 "Example: %s -d fflog -c openni_image_rgb 0..1355421345807\n"
56 main(
int argc,
char **argv)
59 if (argp.has_arg(
"h")) {
64 const std::vector<const char *> &items = argp.items();
66 std::string output_dir =
"tmp/";
67 std::string db_name =
"fflog";
68 std::string collection_name;
69 std::string query_coll;
70 bool filename_indexed = !argp.has_arg(
"f");
72 std::vector<std::pair<long long, long long>> times;
74 if (argp.has_arg(
"o")) {
75 output_dir = argp.arg(
"o");
76 if (output_dir[output_dir.length() - 1] !=
'/') {
80 if (argp.has_arg(
"d")) {
81 db_name = argp.arg(
"d");
83 if (argp.has_arg(
"c")) {
84 collection_name = argp.arg(
"c");
87 printf(
"No collection given\n");
92 times.push_back(std::make_pair(0L, std::numeric_limits<long long>::max()));
94 for (
unsigned int i = 0; i < items.size(); ++i) {
95 std::string item = items[i];
96 std::string::size_type dotpos = item.find(
"..");
97 if (dotpos == std::string::npos) {
99 long int ts = argp.parse_item_int(i);
100 times.push_back(std::make_pair(ts, ts));
103 std::string first_ts, second_ts;
104 first_ts = item.substr(0, dotpos);
105 second_ts = item.substr(dotpos + 2);
106 times.push_back(std::make_pair(StringConversions::to_long(first_ts),
107 StringConversions::to_long(second_ts)));
112 unsigned int image_n = 0;
114 client mongodb_client{uri{
"localhost"}};
115 auto collection = mongodb_client[db_name][collection_name];
117 gridfs::bucket gridfs = mongodb_client[
"fflog"].gridfs_bucket();
119 for (
unsigned int i = 0; i < times.size(); ++i) {
123 cursor cursor = [&]() {
124 if (times[i].first == times[i].second) {
125 printf(
"Querying for timestamp %lli\n", times[i].first);
126 return collection.find(
127 basic::make_document(basic::kvp(
"timestamp", static_cast<int64_t>(times[i].first))),
128 options::find().sort(basic::make_document(basic::kvp(
"timestamp", 1))));
130 printf(
"Querying for range %lli..%lli\n", times[i].first, times[i].second);
131 return collection.find(
132 basic::make_document(
133 basic::kvp(
"timestamp",
134 [times, i](basic::sub_document subdoc) {
135 subdoc.append(basic::kvp(
"$gt", static_cast<int64_t>(times[i].first)));
136 subdoc.append(basic::kvp(
"$lt", static_cast<int64_t>(times[i].second)));
138 options::find().sort(basic::make_document(basic::kvp(
"timestamp", 1))));
143 for (
auto doc : cursor) {
144 auto imgdoc = doc[
"image"];
145 if (imgdoc[
"colorspace"].get_utf8().value.to_string() ==
"RGB") {
146 types::value file_id = imgdoc[
"data"][
"id"].get_value();
147 std::string filename = imgdoc[
"data"][
"filename"].get_utf8().value.to_string();
148 std::string image_id = imgdoc[
"image_id"].get_utf8().value.to_string();
150 std::string out_filename;
152 if (filename_indexed) {
153 if (asprintf(&fntmp,
"%s%s-%08d.png", output_dir.c_str(), image_id.c_str(), image_n++)
155 out_filename = fntmp;
159 if (asprintf(&fntmp,
"%s%s.png", output_dir.c_str(), filename.c_str()) != -1) {
160 out_filename = fntmp;
166 printf(
"Restoring RGB image %s (%s)\n", filename.c_str(), out_filename.c_str());
168 auto downloader = gridfs.open_download_stream(file_id);
169 int64_t filesize = downloader.file_length();
170 int width = imgdoc[
"width"].get_int32();
171 int height = imgdoc[
"height"].get_int32();
173 if (colorspace_buffer_size(RGB, width, height) != (
size_t)filesize) {
174 printf(
"Buffer size mismatch (DB %li vs. exp. %zu)\n",
176 colorspace_buffer_size(RGB, width, height));
180 auto buffer_size = std::min(filesize, static_cast<int64_t>(downloader.chunk_size()));
181 unsigned char *buffer = malloc_buffer(RGB, width, height);
183 unsigned char *tmp = buffer;
184 while (
auto length_read = downloader.read(tmp, buffer_size)) {
188 PNGWriter writer(out_filename.c_str(), width, height);