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/system/argparser.h>
24 #include <utils/misc/string_conversions.h>
25 
26 #include <mongo/client/dbclient.h>
27 #include <mongo/client/gridfs.h>
28 
29 using namespace firevision;
30 using namespace mongo;
31 using namespace fawkes;
32 
33 #ifdef HAVE_MONGODB_VERSION_H
34 // we are using mongo-cxx-driver which renamed QUERY to MONGO_QUERY
35 # define QUERY MONGO_QUERY
36 #endif
37 
38 
39 void
40 print_usage(const char *progname)
41 {
42  printf("Usage: %s [-h] [-o dir] [-f] [-d database] -c collection items...\n"
43  " -h Show this help message\n"
44  " -o dir Output directory where to create PNG files\n"
45  " -f Use original filenames form database\n"
46  " -d database Database to query for images\n"
47  " -c collection Collection to query for images\n"
48  "\n"
49  "Items are either timestamps (ms precision) or timestamp ranges in\n"
50  "the form ts1..ts2\n"
51  "\n"
52  "Example: %s -d fflog -c openni_image_rgb 0..1355421345807\n"
53  "\n", progname, 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 =
118  new DBClientConnection(/* auto reconnect */ true);
119  std::string errmsg;
120  mongodb_client->connect("localhost", errmsg);
121 
122  GridFS *gridfs = new GridFS(*mongodb_client, "fflog");
123 
124 
125  for (unsigned int i = 0; i < times.size(); ++i) {
126  Query q;
127 
128  if (times[i].first == times[i].second) {
129  printf("Querying for timestamp %lli\n", times[i].first);
130  q = QUERY("timestamp" << times[i].first).sort("timestamp", 1);
131  } else {
132  printf("Querying for range %lli..%lli\n", times[i].first, times[i].second);
133  q = QUERY("timestamp"
134  << mongo::GTE << times[i].first
135  << mongo::LTE << times[i].second)
136  .sort("timestamp", 1);
137  }
138 
139 #if __cplusplus >= 201103L
140  std::unique_ptr<mongo::DBClientCursor> cursor =
141  mongodb_client->query(query_coll, q);
142 #else
143  std::auto_ptr<mongo::DBClientCursor> cursor =
144  mongodb_client->query(query_coll, q);
145 #endif
146 
147  while (cursor->more()) {
148  BSONObj doc = cursor->next();
149 
150  BSONObj imgdoc = doc.getObjectField("image");
151  if (imgdoc["colorspace"].String() == "RGB") {
152  std::string filename = imgdoc.getFieldDotted("data.filename").String();
153  long filesize = imgdoc.getFieldDotted("data.length").numberLong();
154  std::string image_id = imgdoc["image_id"].String();
155 
156  std::string out_filename;
157  char *fntmp;
158  if (filename_indexed) {
159  if (asprintf(&fntmp, "%s%s-%08d.png", output_dir.c_str(),
160  image_id.c_str(), image_n++) != -1)
161  {
162  out_filename = fntmp;
163  free(fntmp);
164  }
165  } else {
166  if (asprintf(&fntmp, "%s%s.png", output_dir.c_str(),
167  filename.c_str()) != -1)
168  {
169  out_filename = fntmp;
170  free(fntmp);
171  }
172  ++image_n;
173  }
174 
175  printf("Restoring RGB image %s (%s)\n", filename.c_str(), out_filename.c_str());
176 
177  GridFile file = gridfs->findFile(filename);
178  if (! file.exists()) {
179  printf("File %s does not exist\n", filename.c_str());
180  continue;
181  }
182 
183  unsigned int width = imgdoc["width"].Int();
184  unsigned int height = imgdoc["height"].Int();
185 
186  if (colorspace_buffer_size(RGB, width, height) != (size_t)filesize) {
187  printf("Buffer size mismatch (DB %li vs. exp. %zu)\n",
188  filesize, colorspace_buffer_size(RGB, width, height));
189  continue;
190  }
191 
192  unsigned char *buffer = malloc_buffer(RGB, width, height);
193 
194  unsigned char *tmp = buffer;
195  for (int c = 0; c < file.getNumChunks(); ++c) {
196  mongo::GridFSChunk chunk = file.getChunk(c);
197  int len = 0;
198  const char *chunk_data = chunk.data(len);
199  memcpy(tmp, chunk_data, len);
200  tmp += len;
201  }
202 
203  PNGWriter writer(out_filename.c_str(), width, height);
204  writer.set_buffer(RGB, buffer);
205  writer.write();
206 
207  free(buffer);
208  }
209  }
210  }
211 
212  delete gridfs;
213  delete mongodb_client;
214 
215 }
216 
PNG file writer.
Definition: png.h:34
Fawkes library namespace.
Definition: mongodb.h:29
Parse command line arguments.
Definition: argparser.h:66
virtual void set_buffer(colorspace_t cspace, unsigned char *buffer)
Set image buffer.
Definition: png.cpp:70