stereo-vision
image.h
1 /*
2 Copyright 2011. All rights reserved.
3 Institute of Measurement and Control Systems
4 Karlsruhe Institute of Technology, Germany
5 
6 This file is part of libelas.
7 Authors: Andreas Geiger
8 
9 libelas is free software; you can redistribute it and/or modify it under the
10 terms of the GNU General Public License as published by the Free Software
11 Foundation; either version 3 of the License, or any later version.
12 
13 libelas is distributed in the hope that it will be useful, but WITHOUT ANY
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
15 PARTICULAR PURPOSE. See the GNU General Public License for more details.
16 
17 You should have received a copy of the GNU General Public License along with
18 libelas; if not, write to the Free Software Foundation, Inc., 51 Franklin
19 Street, Fifth Floor, Boston, MA 02110-1301, USA
20 */
21 
22 // basic image I/O, based on Pedro Felzenszwalb's code
23 
24 #ifndef IMAGE_H
25 #define IMAGE_H
26 
27 #include <cstdlib>
28 #include <climits>
29 #include <cstring>
30 #include <fstream>
31 
32 // use imRef to access image data.
33 #define imRef(im, x, y) (im->access[y][x])
34 
35 // use imPtr to get pointer to image data.
36 #define imPtr(im, x, y) &(im->access[y][x])
37 
38 #define BUF_SIZE 256
39 
40 typedef unsigned char uchar;
41 typedef struct { uchar r, g, b; } rgb;
42 
43 inline bool operator==(const rgb &a, const rgb &b) {
44  return ((a.r == b.r) && (a.g == b.g) && (a.b == b.b));
45 }
46 
47 // image class
48 template <class T> class image {
49 public:
50 
51  // create image
52  image(const int width, const int height, const bool init = false);
53 
54  // delete image
55  ~image();
56 
57  // init image
58  void init(const T &val);
59 
60  // deep copy
61  image<T> *copy() const;
62 
63  // get image width/height
64  int width() const { return w; }
65  int height() const { return h; }
66 
67  // image data
68  T *data;
69 
70  // row pointers
71  T **access;
72 
73 private:
74  int w, h;
75 };
76 
77 template <class T> image<T>::image(const int width, const int height, const bool init) {
78  w = width;
79  h = height;
80  data = new T[w * h]; // allocate space for image data
81  access = new T*[h]; // allocate space for row pointers
82 
83  // initialize row pointers
84  for (int i = 0; i < h; i++)
85  access[i] = data + (i * w);
86 
87  // init to zero
88  if (init)
89  memset(data, 0, w * h * sizeof(T));
90 }
91 
92 template <class T> image<T>::~image() {
93  delete [] data;
94  delete [] access;
95 }
96 
97 template <class T> void image<T>::init(const T &val) {
98  T *ptr = imPtr(this, 0, 0);
99  T *end = imPtr(this, w-1, h-1);
100  while (ptr <= end)
101  *ptr++ = val;
102 }
103 
104 
105 template <class T> image<T> *image<T>::copy() const {
106  image<T> *im = new image<T>(w, h, false);
107  memcpy(im->data, data, w * h * sizeof(T));
108  return im;
109 }
110 
111 class pnm_error {};
112 
113 void pnm_read(std::ifstream &file, char *buf) {
114  char doc[BUF_SIZE];
115  char c;
116 
117  file >> c;
118  while (c == '#') {
119  file.getline(doc, BUF_SIZE);
120  file >> c;
121  }
122  file.putback(c);
123 
124  file.width(BUF_SIZE);
125  file >> buf;
126  file.ignore();
127 }
128 
129 image<uchar> *loadPGM(const char *name) {
130  char buf[BUF_SIZE];
131 
132  // read header
133  std::ifstream file(name, std::ios::in | std::ios::binary);
134  pnm_read(file, buf);
135  if (strncmp(buf, "P5", 2)) {
136  std::cout << "ERROR: Could not read file " << name << std::endl;
137  throw pnm_error();
138  }
139 
140  pnm_read(file, buf);
141  int width = atoi(buf);
142  pnm_read(file, buf);
143  int height = atoi(buf);
144 
145  pnm_read(file, buf);
146  if (atoi(buf) > UCHAR_MAX) {
147  std::cout << "ERROR: Could not read file " << name << std::endl;
148  throw pnm_error();
149  }
150 
151  // read data
152  image<uchar> *im = new image<uchar>(width, height);
153  file.read((char *)imPtr(im, 0, 0), width * height * sizeof(uchar));
154 
155  return im;
156 }
157 
158 void savePGM(image<uchar> *im, const char *name) {
159  int width = im->width();
160  int height = im->height();
161  std::ofstream file(name, std::ios::out | std::ios::binary);
162 
163  file << "P5\n" << width << " " << height << "\n" << UCHAR_MAX << "\n";
164  file.write((char *)imPtr(im, 0, 0), width * height * sizeof(uchar));
165 }
166 
167 #endif