Fawkes API Fawkes Development Version
ffmongodb_save_imgs.cpp
1
2/***************************************************************************
3 * ffmongodb_save_imgs.cpp - Save images from database to file
4 *
5 * Created: Fri Dec 14 00:46:58 2012
6 * Copyright 2010-2012 Tim Niemueller [www.niemueller.de]
7 ****************************************************************************/
8
9/* This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU Library General Public License for more details.
18 *
19 * Read the full text in the LICENSE.GPL file in the doc directory.
20 */
21
22#include <fvutils/writers/png.h>
23#include <utils/misc/string_conversions.h>
24#include <utils/system/argparser.h>
25
26#include <mongocxx/client.hpp>
27#include <mongocxx/gridfs/bucket.hpp>
28#include <mongocxx/gridfs/downloader.hpp>
29
30using namespace firevision;
31using namespace mongocxx;
32using namespace fawkes;
33using namespace bsoncxx;
34using namespace bsoncxx::builder;
35
36void
37print_usage(const char *progname)
38{
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"
45 "\n"
46 "Items are either timestamps (ms precision) or timestamp ranges in\n"
47 "the form ts1..ts2\n"
48 "\n"
49 "Example: %s -d fflog -c openni_image_rgb 0..1355421345807\n"
50 "\n",
51 progname,
52 progname);
53}
54
55int
56main(int argc, char **argv)
57{
58 ArgumentParser argp(argc, argv, "ho:fd:c:");
59 if (argp.has_arg("h")) {
60 print_usage(argv[0]);
61 exit(0);
62 }
63
64 const std::vector<const char *> &items = argp.items();
65
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");
71
72 std::vector<std::pair<long long, long long>> times;
73
74 if (argp.has_arg("o")) {
75 output_dir = argp.arg("o");
76 if (output_dir[output_dir.length() - 1] != '/') {
77 output_dir += "/";
78 }
79 }
80 if (argp.has_arg("d")) {
81 db_name = argp.arg("d");
82 }
83 if (argp.has_arg("c")) {
84 collection_name = argp.arg("c");
85 } else {
86 print_usage(argv[0]);
87 printf("No collection given\n");
88 exit(-1);
89 }
90
91 if (items.empty()) {
92 times.push_back(std::make_pair(0L, std::numeric_limits<long long>::max()));
93 } else {
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) {
98 // singular timestamp
99 long int ts = argp.parse_item_int(i);
100 times.push_back(std::make_pair(ts, ts));
101 } else {
102 // range
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)));
108 }
109 }
110 }
111
112 unsigned int image_n = 0;
113
114 client mongodb_client{uri{"localhost"}};
115 auto collection = mongodb_client[db_name][collection_name];
116
117 gridfs::bucket gridfs = mongodb_client["fflog"].gridfs_bucket();
118
119 for (unsigned int i = 0; i < times.size(); ++i) {
120 // Initialize the cursor with a lambda because there is no default
121 // constructor and we cannot define the cursor inside the conditional
122 // branches.
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))));
129 } else {
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)));
137 })),
138 options::find().sort(basic::make_document(basic::kvp("timestamp", 1))));
139 }
140 }();
141
142 //auto it = cursor.begin();
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();
149
150 std::string out_filename;
151 char * fntmp;
152 if (filename_indexed) {
153 if (asprintf(&fntmp, "%s%s-%08d.png", output_dir.c_str(), image_id.c_str(), image_n++)
154 != -1) {
155 out_filename = fntmp;
156 free(fntmp);
157 }
158 } else {
159 if (asprintf(&fntmp, "%s%s.png", output_dir.c_str(), filename.c_str()) != -1) {
160 out_filename = fntmp;
161 free(fntmp);
162 }
163 ++image_n;
164 }
165
166 printf("Restoring RGB image %s (%s)\n", filename.c_str(), out_filename.c_str());
167
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();
172
173 if (colorspace_buffer_size(RGB, width, height) != (size_t)filesize) {
174 printf("Buffer size mismatch (DB %li vs. exp. %zu)\n",
175 filesize,
176 colorspace_buffer_size(RGB, width, height));
177 continue;
178 }
179
180 auto buffer_size = std::min(filesize, static_cast<int64_t>(downloader.chunk_size()));
181 unsigned char *buffer = malloc_buffer(RGB, width, height);
182
183 unsigned char *tmp = buffer;
184 while (auto length_read = downloader.read(tmp, buffer_size)) {
185 tmp += length_read;
186 }
187
188 PNGWriter writer(out_filename.c_str(), width, height);
189 writer.set_buffer(RGB, buffer);
190 writer.write();
191
192 free(buffer);
193 }
194 //std::advance(it, 1);
195 }
196 }
197}
Parse command line arguments.
Definition: argparser.h:64
PNG file writer.
Definition: png.h:32
Fawkes library namespace.