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 
30 using namespace firevision;
31 using namespace mongocxx;
32 using namespace fawkes;
33 using namespace bsoncxx;
34 using namespace bsoncxx::builder;
35 
36 void
37 print_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 
55 int
56 main(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.