Optimized Belief Propagation (CPU and GPU)
pnmfile.h
Go to the documentation of this file.
1 /*
2 Copyright (C) 2006 Pedro Felzenszwalb
3 
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
8 
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13 
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 */
18 
19 /* basic image I/O */
20 
21 #ifndef PNM_FILE_H
22 #define PNM_FILE_H
23 
24 #include <cstdlib>
25 #include <climits>
26 #include <cstring>
27 #include <fstream>
28 #include "image.h"
29 #include "misc.h"
30 
31 #define BUF_SIZE 256
33 
38 namespace bp_single_thread_imp {
39 class pnm_error { };
40 }
41 /*static void read_packed(unsigned char *data, int size, std::ifstream &f) {
42  unsigned char c = 0;
43 
44  int bitshift = -1;
45  for (int pos = 0; pos < size; pos++) {
46  if (bitshift == -1) {
47  c = f.get();
48  bitshift = 7;
49  }
50  data[pos] = (c >> bitshift) & 1;
51  bitshift--;
52  }
53 }*/
54 
55 /*static void write_packed(unsigned char *data, int size, std::ofstream &f) {
56  unsigned char c = 0;
57 
58  int bitshift = 7;
59  for (int pos = 0; pos < size; pos++) {
60  c = c | (data[pos] << bitshift);
61  bitshift--;
62  if ((bitshift == -1) || (pos == size-1)) {
63  f.put(c);
64  bitshift = 7;
65  c = 0;
66  }
67  }
68 }*/
69 
70 /* read PNM field, skipping comments */
71 static void pnm_read(std::ifstream &file, std::string& buf) {
72  char doc[BUF_SIZE];
73  char c;
74 
75  file >> c;
76  while (c == '#') {
77  file.getline(doc, BUF_SIZE);
78  file >> c;
79  }
80  file.putback(c);
81 
82  file.width(BUF_SIZE);
83  file >> buf;
84  file.ignore();
85 }
86 
87 /*static image<uchar> *loadPBM(const char *name) {
88  std::string buf;
89 
90  //read header
91  std::ifstream file(name, std::ios::in | std::ios::binary);
92  pnm_read(file, buf);
93  if (strncmp(buf.c_str(), "P4", 2))
94  throw bp_single_thread_imp::pnm_error();
95 
96  pnm_read(file, buf);
97  int width = std::stoi(buf);
98  pnm_read(file, buf);
99  int height = std::stoi(buf);
100 
101  //read data
102  image<uchar> *im = new image<uchar>(width, height);
103  for (int i = 0; i < height; i++)
104  read_packed(imPtr(im, 0, i), width, file);
105 
106  return im;
107 }*/
108 
109 /*static void savePBM(image<uchar> *im, const char *name) {
110  int width = im->width();
111  int height = im->height();
112  std::ofstream file(name, std::ios::out | std::ios::binary);
113 
114  file << "P4\n" << width << " " << height << "\n";
115  for (int i = 0; i < height; i++)
116  write_packed(imPtr(im, 0, i), width, file);
117 }*/
118 
119 static bp_single_thread_imp::image<uchar> *loadPGM(const char *name) {
120  std::string buf;
121 
122  /* read header */
123  std::ifstream file(name, std::ios::in | std::ios::binary);
124  pnm_read(file, buf);
125  if (strncmp(buf.c_str(), "P5", 2))
127 
128  pnm_read(file, buf);
129  int width = std::stoi(buf);
130  pnm_read(file, buf);
131  int height = std::stoi(buf);
132 
133  pnm_read(file, buf);
134  if (std::stoi(buf) > UCHAR_MAX)
136 
137  /* read data */
139  file.read((char *)imPtr(im, 0, 0), width * height * sizeof(uchar));
140 
141  return im;
142 }
143 
144 /*static void savePGM(image<uchar> *im, const char *name) {
145  int width = im->width();
146  int height = im->height();
147  std::ofstream file(name, std::ios::out | std::ios::binary);
148 
149  file << "P5\n" << width << " " << height << "\n" << UCHAR_MAX << "\n";
150  file.write((char *)imPtr(im, 0, 0), width * height * sizeof(uchar));
151 }*/
152 
153 /*static image<bp_single_thread_imp::rgb> *loadPPM(const char *name) {
154  std::string buf;
155 
156  //read header
157  std::ifstream file(name, std::ios::in | std::ios::binary);
158  pnm_read(file, buf);
159  if (strncmp(buf.c_str(), "P6", 2))
160  throw bp_single_thread_imp::pnm_error();
161 
162  pnm_read(file, buf);
163  int width = std::stoi(buf);
164  pnm_read(file, buf);
165  int height = std::stoi(buf);
166 
167  pnm_read(file, buf);
168  if (std::stoi(buf) > UCHAR_MAX)
169  throw bp_single_thread_imp::pnm_error();
170 
171  //read data
172  image<bp_single_thread_imp::rgb> *im = new image<bp_single_thread_imp::rgb>(width, height);
173  file.read((char *)imPtr(im, 0, 0), width * height * sizeof(bp_single_thread_imp::rgb));
174 
175  return im;
176 }*/
177 
178 static bp_single_thread_imp::image<uchar> *loadPPMAndConvertToGrayScale(const char *name) {
179  std::string buf;
180 
181  /* read header */
182  std::ifstream file(name, std::ios::in | std::ios::binary);
183  pnm_read(file, buf);
184  if (strncmp(buf.c_str(), "P6", 2))
186 
187  pnm_read(file, buf);
188  int width = std::stoi(buf);
189  pnm_read(file, buf);
190  int height = std::stoi(buf);
191 
192  pnm_read(file, buf);
193  if (std::stoi(buf) > UCHAR_MAX)
195 
196  /* read data */
199  file.read((char *)imPtr(im, 0, 0), width * height * sizeof(bp_single_thread_imp::rgb));
200 
201  float r_channel_weight = 1.0f / 3.0f;
202  float g_channel_weight = 1.0f / 3.0f;
203  float b_channel_weight = 1.0f / 3.0f;
205  {
206  r_channel_weight = 0.299f;
207  g_channel_weight = 0.114f;
208  b_channel_weight = 0.587f;
209  }
210 
211  for (int i=0; i<width; i++)
212  {
213  for (int j=0; j<height; j++)
214  {
215  imRef(imGrayScale, i, j) = floor(((float)imRef(im, i, j).r)*r_channel_weight + ((float)imRef(im, i, j).g)*g_channel_weight + ((float)imRef(im, i, j).b)*b_channel_weight + 0.5f);
216  }
217  }
218  delete im;
219 
220  return imGrayScale;
221 }
222 
223 
224 /*static void savePPM(image<bp_single_thread_imp::rgb> *im, const char *name) {
225  int width = im->width();
226  int height = im->height();
227  std::ofstream file(name, std::ios::out | std::ios::binary);
228 
229  file << "P6\n" << width << " " << height << "\n" << UCHAR_MAX << "\n";
230  file.write((char *)imPtr(im, 0, 0), width * height * sizeof(bp_single_thread_imp::rgb));
231 }*/
232 
233 static bp_single_thread_imp::image<uchar> *loadPGMOrPPMImage(const char *name) {
234  char pgmExtension[] = "pgm";
235  char ppmExtension[] = "ppm";
236  char* file_path_image_copy = new char[strlen(name) + 1]{};
237  std::copy(name, name + strlen(name), file_path_image_copy);
238 
239  //check if PGM or PPM image (types currently supported)
240 #ifdef _WIN32
241  char* next_token;
242  char* token;
243  token = strtok_s(file_path_image_copy, ".", &next_token);
244 #else
245  char* token = strtok(file_path_image_copy, ".");
246 #endif //_WIN32
247  char* lastToken = new char[strlen(token) + 1]{};
248  std::copy(token, token + strlen(token), lastToken);
249  while( token != NULL )
250  {
251  delete [] lastToken;
252  lastToken = new char[strlen(token) + 1]{};
253  std::copy(token, token + strlen(token), lastToken);
254 #ifdef _WIN32
255  token = strtok_s(NULL, ".", &next_token);
256 #else
257  token = strtok(NULL, ".");
258 #endif //_WIN32
259  }
260 
261  //last token after "." is file extension
262  if (strcmp(lastToken, pgmExtension) == 0)
263  {
264  delete [] file_path_image_copy;
265 
266  // load input pgm image
267  return loadPGM(name);
268  }
269  else if (strcmp(lastToken, ppmExtension) == 0)
270  {
271  delete [] file_path_image_copy;
272 
273  // load input ppm image
274  return loadPPMAndConvertToGrayScale(name);
275  }
276  else
277  {
278  delete [] file_path_image_copy;
279  std::cout << "CPU ERROR, IMAGE FILE " << name << " NOT SUPPORTED\n";
280  return NULL;
281  }
282 }
283 
284 template <class T>
285 void load_image(bp_single_thread_imp::image<T> **im, const char *name) {
286  std::string buf;
287 
288  /* read header */
289  std::ifstream file(name, std::ios::in | std::ios::binary);
290  pnm_read(file, buf);
291  if (strncmp(buf.c_str(), "VLIB", 9))
293 
294  pnm_read(file, buf);
295  int width = std::stoi(buf);
296  pnm_read(file, buf);
297  int height = std::stoi(buf);
298 
299  /* read data */
300  *im = new bp_single_thread_imp::image<T>(width, height);
301  file.read((char *)imPtr((*im), 0, 0), width * height * sizeof(T));
302 }
303 
304 template <class T>
305 void save_image(bp_single_thread_imp::image<T> *im, const char *name) {
306  int width = im->width();
307  int height = im->height();
308  std::ofstream file(name, std::ios::out | std::ios::binary);
309 
310  file << "VLIB\n" << width << " " << height << "\n";
311  file.write((char *)imPtr(im, 0, 0), width * height * sizeof(T));
312 }
313 
314 #endif
int height() const
Definition: image.h:51
#define imPtr(im, x, y)
Definition: image.h:67
#define imRef(im, x, y)
Definition: image.h:64
unsigned char uchar
Definition: misc.h:30
Class and structs in single-thread CPU bp implementation by Pedro Felzenwalb available at https://cs....
Definition: convolve.h:33
#define BUF_SIZE
Definition: pnmfile.h:31
void load_image(bp_single_thread_imp::image< T > **im, const char *name)
Definition: pnmfile.h:285
void save_image(bp_single_thread_imp::image< T > *im, const char *name)
Definition: pnmfile.h:305
const bool kUseWeightedRGBToGrayscaleConversion_PNMFILE
Definition: pnmfile.h:32