segmentation
All Data Structures Namespaces Files Functions Variables Modules Pages
pnmfile.h
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
32 
33 class pnm_error { };
34 
35 static void read_packed(unsigned char *data, int size, std::ifstream &f) {
36  unsigned char c = 0;
37 
38  int bitshift = -1;
39  for (int pos = 0; pos < size; pos++) {
40  if (bitshift == -1) {
41  c = f.get();
42  bitshift = 7;
43  }
44  data[pos] = (c >> bitshift) & 1;
45  bitshift--;
46  }
47 }
48 
49 static void write_packed(unsigned char *data, int size, std::ofstream &f) {
50  unsigned char c = 0;
51 
52  int bitshift = 7;
53  for (int pos = 0; pos < size; pos++) {
54  c = c | (data[pos] << bitshift);
55  bitshift--;
56  if ((bitshift == -1) || (pos == size-1)) {
57  f.put(c);
58  bitshift = 7;
59  c = 0;
60  }
61  }
62 }
63 
64 /* read PNM field, skipping comments */
65 static void pnm_read(std::ifstream &file, char *buf) {
66  char doc[BUF_SIZE];
67  char c;
68 
69  file >> c;
70  while (c == '#') {
71  file.getline(doc, BUF_SIZE);
72  file >> c;
73  }
74  file.putback(c);
75 
76  file.width(BUF_SIZE);
77  file >> buf;
78  file.ignore();
79 }
80 
81 static image<uchar> *loadPBM(const char *name) {
82  char buf[BUF_SIZE];
83 
84  /* read header */
85  std::ifstream file(name, std::ios::in | std::ios::binary);
86  pnm_read(file, buf);
87  if (strncmp(buf, "P4", 2))
88  throw pnm_error();
89 
90  pnm_read(file, buf);
91  int width = atoi(buf);
92  pnm_read(file, buf);
93  int height = atoi(buf);
94 
95  /* read data */
96  image<uchar> *im = new image<uchar>(width, height);
97  for (int i = 0; i < height; i++)
98  read_packed(imPtr(im, 0, i), width, file);
99 
100  return im;
101 }
102 
103 static void savePBM(image<uchar> *im, const char *name) {
104  int width = im->width();
105  int height = im->height();
106  std::ofstream file(name, std::ios::out | std::ios::binary);
107 
108  file << "P4\n" << width << " " << height << "\n";
109  for (int i = 0; i < height; i++)
110  write_packed(imPtr(im, 0, i), width, file);
111 }
112 
113 static image<uchar> *loadPGM(const char *name) {
114  char buf[BUF_SIZE];
115 
116  /* read header */
117  std::ifstream file(name, std::ios::in | std::ios::binary);
118  pnm_read(file, buf);
119  if (strncmp(buf, "P5", 2))
120  throw pnm_error();
121 
122  pnm_read(file, buf);
123  int width = atoi(buf);
124  pnm_read(file, buf);
125  int height = atoi(buf);
126 
127  pnm_read(file, buf);
128  if (atoi(buf) > UCHAR_MAX)
129  throw pnm_error();
130 
131  /* read data */
132  image<uchar> *im = new image<uchar>(width, height);
133  file.read((char *)imPtr(im, 0, 0), width * height * sizeof(uchar));
134 
135  return im;
136 }
137 
138 static void savePGM(image<uchar> *im, const char *name) {
139  int width = im->width();
140  int height = im->height();
141  std::ofstream file(name, std::ios::out | std::ios::binary);
142 
143  file << "P5\n" << width << " " << height << "\n" << UCHAR_MAX << "\n";
144  file.write((char *)imPtr(im, 0, 0), width * height * sizeof(uchar));
145 }
146 
147 static image<rgb> *loadPPM(const char *name) {
148  char buf[BUF_SIZE], doc[BUF_SIZE];
149 
150  /* read header */
151  std::ifstream file(name, std::ios::in | std::ios::binary);
152  pnm_read(file, buf);
153  if (strncmp(buf, "P6", 2))
154  throw pnm_error();
155 
156  pnm_read(file, buf);
157  int width = atoi(buf);
158  pnm_read(file, buf);
159  int height = atoi(buf);
160 
161  pnm_read(file, buf);
162  if (atoi(buf) > UCHAR_MAX)
163  throw pnm_error();
164 
165  /* read data */
166  image<rgb> *im = new image<rgb>(width, height);
167  file.read((char *)imPtr(im, 0, 0), width * height * sizeof(rgb));
168 
169  return im;
170 }
171 
172 static void savePPM(image<rgb> *im, const char *name) {
173  int width = im->width();
174  int height = im->height();
175  std::ofstream file(name, std::ios::out | std::ios::binary);
176 
177  file << "P6\n" << width << " " << height << "\n" << UCHAR_MAX << "\n";
178  file.write((char *)imPtr(im, 0, 0), width * height * sizeof(rgb));
179 }
180 
181 template <class T>
182 void load_image(image<T> **im, const char *name) {
183  char buf[BUF_SIZE];
184 
185  /* read header */
186  std::ifstream file(name, std::ios::in | std::ios::binary);
187  pnm_read(file, buf);
188  if (strncmp(buf, "VLIB", 9))
189  throw pnm_error();
190 
191  pnm_read(file, buf);
192  int width = atoi(buf);
193  pnm_read(file, buf);
194  int height = atoi(buf);
195 
196  /* read data */
197  *im = new image<T>(width, height);
198  file.read((char *)imPtr((*im), 0, 0), width * height * sizeof(T));
199 }
200 
201 template <class T>
202 void save_image(image<T> *im, const char *name) {
203  int width = im->width();
204  int height = im->height();
205  std::ofstream file(name, std::ios::out | std::ios::binary);
206 
207  file << "VLIB\n" << width << " " << height << "\n";
208  file.write((char *)imPtr(im, 0, 0), width * height * sizeof(T));
209 }
210 
211 #endif