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 <mongo/client/dbclient.h>
24 #include <mongo/client/gridfs.h>
25 #include <utils/misc/string_conversions.h>
26 #include <utils/system/argparser.h>
27 
28 using namespace firevision;
29 using namespace mongo;
30 using namespace fawkes;
31 
32 #ifdef HAVE_MONGODB_VERSION_H
33 // we are using mongo-cxx-driver which renamed QUERY to MONGO_QUERY
34 # define QUERY MONGO_QUERY
35 #endif
36 
37 void
38 print_usage(const char *progname)
39 {
40  printf("Usage: %s [-h] [-o dir] [-f] [-d database] -c collection items...\n"
41  " -h Show this help message\n"
42  " -o dir Output directory where to create PNG files\n"
43  " -f Use original filenames form database\n"
44  " -d database Database to query for images\n"
45  " -c collection Collection to query for images\n"
46  "\n"
47  "Items are either timestamps (ms precision) or timestamp ranges in\n"
48  "the form ts1..ts2\n"
49  "\n"
50  "Example: %s -d fflog -c openni_image_rgb 0..1355421345807\n"
51  "\n",
52  progname,
53  progname);
54 }
55 
56 int
57 main(int argc, char **argv)
58 {
59  ArgumentParser argp(argc, argv, "ho:fd:c:");
60  if (argp.has_arg("h")) {
61  print_usage(argv[0]);
62  exit(0);
63  }
64 
65  const std::vector<const char *> &items = argp.items();
66 
67  std::string output_dir = "tmp/";
68  std::string database = "fflog";
69  std::string collection;
70  std::string query_coll;
71  bool filename_indexed = !argp.has_arg("f");
72 
73  std::vector<std::pair<long long, long long>> times;
74 
75  if (argp.has_arg("o")) {
76  output_dir = argp.arg("o");
77  if (output_dir[output_dir.length() - 1] != '/') {
78  output_dir += "/";
79  }
80  }
81  if (argp.has_arg("d")) {
82  database = argp.arg("d");
83  }
84  if (argp.has_arg("c")) {
85  collection = argp.arg("c");
86  } else {
87  print_usage(argv[0]);
88  printf("No collection given\n");
89  exit(-1);
90  }
91 
92  query_coll = database + "." + collection;
93 
94  if (items.empty()) {
95  times.push_back(std::make_pair(0L, std::numeric_limits<long long>::max()));
96  } else {
97  for (unsigned int i = 0; i < items.size(); ++i) {
98  std::string item = items[i];
99  std::string::size_type dotpos = item.find("..");
100  if (dotpos == std::string::npos) {
101  // singular timestamp
102  long int ts = argp.parse_item_int(i);
103  times.push_back(std::make_pair(ts, ts));
104  } else {
105  // range
106  std::string first_ts, second_ts;
107  first_ts = item.substr(0, dotpos);
108  second_ts = item.substr(dotpos + 2);
109  times.push_back(std::make_pair(StringConversions::to_long(first_ts),
110  StringConversions::to_long(second_ts)));
111  }
112  }
113  }
114 
115  unsigned int image_n = 0;
116 
117  DBClientConnection *mongodb_client = new DBClientConnection(/* auto reconnect */ true);
118  std::string errmsg;
119  mongodb_client->connect("localhost", errmsg);
120 
121  GridFS *gridfs = new GridFS(*mongodb_client, "fflog");
122 
123  for (unsigned int i = 0; i < times.size(); ++i) {
124  Query q;
125 
126  if (times[i].first == times[i].second) {
127  printf("Querying for timestamp %lli\n", times[i].first);
128  q = QUERY("timestamp" << times[i].first).sort("timestamp", 1);
129  } else {
130  printf("Querying for range %lli..%lli\n", times[i].first, times[i].second);
131  q = QUERY("timestamp" << mongo::GTE << times[i].first << mongo::LTE << times[i].second)
132  .sort("timestamp", 1);
133  }
134 
135 #if __cplusplus >= 201103L
136  std::unique_ptr<mongo::DBClientCursor> cursor = mongodb_client->query(query_coll, q);
137 #else
138  std::auto_ptr<mongo::DBClientCursor> cursor = mongodb_client->query(query_coll, q);
139 #endif
140 
141  while (cursor->more()) {
142  BSONObj doc = cursor->next();
143 
144  BSONObj imgdoc = doc.getObjectField("image");
145  if (imgdoc["colorspace"].String() == "RGB") {
146  std::string filename = imgdoc.getFieldDotted("data.filename").String();
147  long filesize = imgdoc.getFieldDotted("data.length").numberLong();
148  std::string image_id = imgdoc["image_id"].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  GridFile file = gridfs->findFile(filename);
169  if (!file.exists()) {
170  printf("File %s does not exist\n", filename.c_str());
171  continue;
172  }
173 
174  unsigned int width = imgdoc["width"].Int();
175  unsigned int height = imgdoc["height"].Int();
176 
177  if (colorspace_buffer_size(RGB, width, height) != (size_t)filesize) {
178  printf("Buffer size mismatch (DB %li vs. exp. %zu)\n",
179  filesize,
180  colorspace_buffer_size(RGB, width, height));
181  continue;
182  }
183 
184  unsigned char *buffer = malloc_buffer(RGB, width, height);
185 
186  unsigned char *tmp = buffer;
187  for (int c = 0; c < file.getNumChunks(); ++c) {
188  mongo::GridFSChunk chunk = file.getChunk(c);
189  int len = 0;
190  const char * chunk_data = chunk.data(len);
191  memcpy(tmp, chunk_data, len);
192  tmp += len;
193  }
194 
195  PNGWriter writer(out_filename.c_str(), width, height);
196  writer.set_buffer(RGB, buffer);
197  writer.write();
198 
199  free(buffer);
200  }
201  }
202  }
203 
204  delete gridfs;
205  delete mongodb_client;
206 }
PNG file writer.
Definition: png.h:31
Fawkes library namespace.
Parse command line arguments.
Definition: argparser.h:63
virtual void set_buffer(colorspace_t cspace, unsigned char *buffer)
Set image buffer.
Definition: png.cpp:65