SigPack - the C++ signal processing library
image.h
Go to the documentation of this file.
1 #ifndef IMAGE_H_INCLUDED
2 #define IMAGE_H_INCLUDED
3 
4 #include <string>
5 #include <fstream>
6 #include <bitset>
7 
8 namespace sp
9 {
14 
21 
22 class PNM
23 {
24 private:
25  std::ifstream ifs;
26  std::ofstream ofs;
27  arma::uword cols;
28  arma::uword rows;
29  int maxval;
30 public:
31  enum imtype
32  {
40  } type;
41 
45  PNM()
46  {
47  type = NOTUSED;
48  cols = 0;
49  rows = 0;
50  maxval = 0;
51  }
52 
56  ~PNM() {}
57 
61  void clear(void)
62  {
63  type = NOTUSED;
64  cols = 0;
65  rows = 0;
66  maxval = 0;
67  }
68 
73  void read_header()
74  {
75  std::string str;
76  while (ifs >> str) // Read until we have maxval
77  {
78  // Remove comments
79  size_t mark = str.find_first_of("#");
80  if (mark != std::string::npos)
81  {
82  ifs.ignore(256, '\n');
83  str.erase(mark, 1);
84 
85  if (str.empty())
86  continue;
87  }
88 
89  if (type == NOTUSED)
90  {
91  type = static_cast<imtype>(str.at(1) - 48); // Conv char to int
92  if (str.at(0) != 'P' || type > PPM_B)
93  err_handler("Wrong type!");
94  }
95  else if (cols == 0)
96  {
97  cols = atoi(str.c_str());
98  }
99  else if (rows == 0)
100  {
101  rows = atoi(str.c_str());
102  if (type == PBM_A || type == PBM_B)
103  {
104  maxval = 1; // Set maxval=1 for .PBM types
105  break;
106  }
107  }
108  else if (maxval == 0)
109  {
110  maxval = atoi(str.c_str());
111  break;
112  }
113  }
114  ifs.ignore(1); // Skip one char before data
115  }
116 
126  void write_header(const imtype _type, const arma::uword _rows,
127  const arma::uword _cols, const int _maxval,
128  const std::string comments)
129  {
130  type = _type;
131  rows = _rows;
132  cols = _cols;
133  maxval = _maxval;
134  ofs << "P" << type << std::endl;
135  ofs << "# " << comments << std::endl;
136  ofs << cols << " " << rows << std::endl;
137  if (!((type == PBM_A) || (type == PBM_B)))
138  ofs << maxval << std::endl;
139  }
140 
150  bool write(std::string fname, const imtype _type, const arma::cube &img,
151  const std::string info = "")
152  {
153  // Open file
154  ofs.open(fname.c_str(), std::ofstream::binary);
155  if (!ofs.good())
156  {
157  std::cout << "Could not open " << fname << std::endl;
158  return false;
159  }
160  else
161  {
162  write_header(_type, img.n_rows, img.n_cols, (int)img.max(), info);
163  // get_info();
164 
165  // Write data
166  if (type == PPM_A) // Plain (ASCII )type
167  {
168  for (arma::uword r = 0; r < rows; r++)
169  {
170  arma::uword i = 0;
171  for (arma::uword c = 0; c < cols; c++)
172  {
173  ofs << img(r, c, 0) << " " << img(r, c, 1) << " " << img(r, c, 2)
174  << " "; // R G B
175  if (++i % 5 == 0)
176  ofs << std::endl; // Max len is 70 chars/line
177  }
178  }
179  }
180  else if (type == PPM_B)
181  {
182  for (arma::uword r = 0; r < rows; r++)
183  for (arma::uword c = 0; c < cols; c++)
184  {
185  unsigned char bb;
186  bb = static_cast<unsigned char>(img(r, c, 0)); // R
187  ofs.write(reinterpret_cast<char *>(&bb), 1);
188  bb = static_cast<unsigned char>(img(r, c, 1)); // G
189  ofs.write(reinterpret_cast<char *>(&bb), 1);
190  bb = static_cast<unsigned char>(img(r, c, 2)); // B
191  ofs.write(reinterpret_cast<char *>(&bb), 1);
192  }
193  }
194  }
195  ofs.close();
196  return true;
197  }
198 
208  bool write(std::string fname, const imtype _type, arma::mat &img,
209  const std::string info = "")
210  {
211  // Open file
212  ofs.open(fname.c_str(), std::ofstream::binary);
213  if (!ofs.good())
214  {
215  std::cout << "Could not open " << fname << std::endl;
216  return false;
217  }
218  else
219  {
220  write_header(_type, img.n_rows, img.n_cols, (int)img.max(), info);
221  // get_info();
222 
223  // Write data
224  if (type == PBM_A || type == PGM_A) // Plain (ASCII )type
225  {
226  arma::uword i = 0;
227  for (arma::mat::iterator ii = img.begin(); ii != img.end(); ++ii)
228  {
229  ofs << *ii << " ";
230  if (++i % 11 == 0)
231  ofs << std::endl; // Max len is 70 chars/line
232  }
233  }
234  else if (type == PBM_B) // Raw .pbm
235  {
236  std::bitset<8> b;
237  for (arma::uword r = 0; r < rows; r++)
238  for (arma::uword c = 0; c < cols; c++)
239  {
240  arma::uword ix = 7 - (c % 8);
241  b[ix] = (img(r, c) > 0);
242  if (ix == 0 || c == cols - 1)
243  {
244  ofs.write(reinterpret_cast<char *>(&b), 1);
245  b.reset();
246  }
247  }
248  }
249  else if (type == PGM_B) // Raw .pgm
250  {
251  if (maxval <= 255)
252  {
253  for (arma::uword r = 0; r < rows; r++)
254  for (arma::uword c = 0; c < cols; c++)
255  {
256  unsigned char bb = static_cast<unsigned char>(img(r, c));
257  ofs.write(reinterpret_cast<char *>(&bb), 1);
258  }
259  }
260  else
261  {
262  for (arma::uword r = 0; r < rows; r++)
263  for (arma::uword c = 0; c < cols; c++)
264  {
265  unsigned int bb;
266  bb = ((static_cast<unsigned int>(img(r, c))) >> 8) &
267  0x00ff; // Write MSB first
268  ofs.write(reinterpret_cast<char *>(&bb), 1);
269  bb = static_cast<unsigned int>(img(r, c)) & 0x00ff;
270  ofs.write(reinterpret_cast<char *>(&bb), 1);
271  }
272  }
273  }
274  }
275 
276  ofs.close();
277  return true;
278  }
279 
284  void get_info()
285  {
286  std::cout << "Type: P" << type << std::endl;
287  std::cout << "cols: " << cols << std::endl;
288  std::cout << "rows: " << rows << std::endl;
289  if (type == PGM_A || type == PGM_B)
290  std::cout << "Maxval: " << maxval << std::endl;
291  }
292 
298  arma::uword get_rows() { return rows; }
299 
305  arma::uword get_cols() { return cols; }
306 
312  int get_maxval() { return maxval; }
313 
321  bool read(std::string fname, arma::cube &img)
322  {
323  // Open file
324  ifs.open(fname.c_str(), std::ifstream::binary);
325  if (!ifs.good())
326  {
327  std::cout << "Could not open " << fname << std::endl;
328  return false;
329  }
330  else
331  {
332  read_header();
333  // get_info();
334 
335  img.set_size(rows, cols, 3);
336  arma::uword r = 0, c = 0;
337  // Get the data
338  if (type == PPM_A) // Plain .PPM
339  {
340  std::string str;
341  arma::uword i = 0;
342  while (ifs >> str && r < rows) // Read until eof
343  {
344  // Remove comments
345  size_t mark = str.find_first_of("#");
346  if (mark != std::string::npos)
347  {
348  ifs.ignore(256, '\n');
349  str.erase(mark, 1);
350 
351  if (str.empty())
352  continue;
353  }
354  int pix = atoi(str.c_str()); // Convert to int
355 
356  img(r, c, i % 3) = pix;
357  i++;
358  if (i % 3 == 0)
359  if (++c == cols)
360  {
361  c = 0;
362  r++;
363  }
364  }
365  }
366  else if (type == PPM_B) // Raw .PPM
367  {
368  for (arma::uword r = 0; r < rows; r++)
369  for (arma::uword c = 0; c < cols; c++)
370  {
371  unsigned char bb;
372  ifs.read(reinterpret_cast<char *>(&bb), 1); // R
373  img(r, c, 0) = bb;
374  ifs.read(reinterpret_cast<char *>(&bb), 1); // G
375  img(r, c, 1) = bb;
376  ifs.read(reinterpret_cast<char *>(&bb), 1); // B
377  img(r, c, 2) = bb;
378  }
379  }
380  }
381  ifs.close();
382  return true;
383  }
384 
392  bool read(std::string fname, arma::mat &img)
393  {
394  // Open file
395  ifs.open(fname.c_str(), std::ifstream::binary);
396  if (!ifs.good())
397  {
398  std::cout << "Could not open " << fname << std::endl;
399  return false;
400  }
401  else
402  {
403  read_header();
404  get_info();
405 
406  img.set_size(rows, cols);
407  arma::uword r = 0, c = 0;
408  // Get the data
409  if (type == PBM_A || type == PGM_A) // Plain .PGM or .PBM
410  {
411  std::string str;
412  while (ifs >> str && r < rows) // Read until eof
413  {
414  // Remove comments
415  size_t mark = str.find_first_of("#");
416  if (mark != std::string::npos)
417  {
418  ifs.ignore(256, '\n');
419  str.erase(mark, 1);
420 
421  if (str.empty())
422  continue;
423  }
424  int pix = atoi(str.c_str()); // Convert to int
425  img(r, c) = pix;
426 
427  if (++c == cols)
428  {
429  c = 0;
430  r++;
431  }
432  }
433  }
434  else if (type == PBM_B) // Raw PBM
435  {
436  unsigned char ch;
437  while (ifs.read(reinterpret_cast<char *>(&ch), 1) &&
438  r < rows) // Read until eof
439  {
440  std::bitset<8> pix(ch);
441  for (int b = 7; b >= 0; b--)
442  {
443  img(r, c) = pix[b];
444  if (++c >= cols)
445  {
446  c = 0;
447  r++;
448  break;
449  }
450  }
451  }
452  }
453  else if (type == PGM_B) // Raw PGM
454  {
455  if (maxval <= 255)
456  {
457  for (arma::uword r = 0; r < rows; r++)
458  for (arma::uword c = 0; c < cols; c++)
459  {
460  unsigned char bb;
461  ifs.read(reinterpret_cast<char *>(&bb), 1);
462  img(r, c) = bb;
463  }
464  }
465  else
466  {
467  for (arma::uword r = 0; r < rows; r++)
468  for (arma::uword c = 0; c < cols; c++)
469  {
470  unsigned char bb[2];
471  ifs.read(reinterpret_cast<char *>(bb), 2);
472  img(r, c) = (bb[0] << 8) + bb[1];
473  }
474  }
475  }
476  }
477  ifs.close();
478  return true;
479  }
480 };
481 
483 } // namespace sp
484 #endif
bool write(std::string fname, const imtype _type, const arma::cube &img, const std::string info="")
Write the .pnm file.
Definition: image.h:150
arma::uword get_cols()
Get nr of cols.
Definition: image.h:305
~PNM()
Destructor.
Definition: image.h:56
std::ifstream ifs
Input stream handle.
Definition: image.h:25
#define err_handler(msg)
Definition: base.h:213
PNM()
Constructor.
Definition: image.h:45
Definition: base.h:7
void read_header()
Reads the .pnm header.
Definition: image.h:73
int maxval
Maximum pixel value in image.
Definition: image.h:29
bool read(std::string fname, arma::mat &img)
Read image.
Definition: image.h:392
bool read(std::string fname, arma::cube &img)
Read image.
Definition: image.h:321
std::ofstream ofs
Output stream handle.
Definition: image.h:26
void clear(void)
Clears the internal variables.
Definition: image.h:61
enum sp::PNM::imtype type
Image format.
imtype
Definition: image.h:31
int get_maxval()
Get maxval.
Definition: image.h:312
arma::uword rows
Nr of rows in image.
Definition: image.h:28
void write_header(const imtype _type, const arma::uword _rows, const arma::uword _cols, const int _maxval, const std::string comments)
Write the .pnm header.
Definition: image.h:126
void get_info()
Prints header info.
Definition: image.h:284
arma::uword cols
Nr of columns in image.
Definition: image.h:27
bool write(std::string fname, const imtype _type, arma::mat &img, const std::string info="")
Write the .pnm file.
Definition: image.h:208
arma::uword get_rows()
Get nr of rows.
Definition: image.h:298
Portable anymap format class.
Definition: image.h:22