00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #ifndef PNM_FILE_H
00022 #define PNM_FILE_H
00023
00024 #include <cstdlib>
00025 #include <climits>
00026 #include <cstring>
00027 #include <fstream>
00028 #include "image.h"
00029 #include "misc.h"
00030
00031 #define BUF_SIZE 256
00032
00033 class pnm_error { };
00034
00035 static void read_packed(unsigned char *data, int size, std::ifstream &f) {
00036 unsigned char c = 0;
00037
00038 int bitshift = -1;
00039 for (int pos = 0; pos < size; pos++) {
00040 if (bitshift == -1) {
00041 c = f.get();
00042 bitshift = 7;
00043 }
00044 data[pos] = (c >> bitshift) & 1;
00045 bitshift--;
00046 }
00047 }
00048
00049 static void write_packed(unsigned char *data, int size, std::ofstream &f) {
00050 unsigned char c = 0;
00051
00052 int bitshift = 7;
00053 for (int pos = 0; pos < size; pos++) {
00054 c = c | (data[pos] << bitshift);
00055 bitshift--;
00056 if ((bitshift == -1) || (pos == size-1)) {
00057 f.put(c);
00058 bitshift = 7;
00059 c = 0;
00060 }
00061 }
00062 }
00063
00064
00065 static void pnm_read(std::ifstream &file, char *buf) {
00066 char doc[BUF_SIZE];
00067 char c;
00068
00069 file >> c;
00070 while (c == '#') {
00071 file.getline(doc, BUF_SIZE);
00072 file >> c;
00073 }
00074 file.putback(c);
00075
00076 file.width(BUF_SIZE);
00077 file >> buf;
00078 file.ignore();
00079 }
00080
00081 static image<uchar> *loadPBM(const char *name) {
00082 char buf[BUF_SIZE];
00083
00084
00085 std::ifstream file(name, std::ios::in | std::ios::binary);
00086 pnm_read(file, buf);
00087 if (strncmp(buf, "P4", 2))
00088 throw pnm_error();
00089
00090 pnm_read(file, buf);
00091 int width = atoi(buf);
00092 pnm_read(file, buf);
00093 int height = atoi(buf);
00094
00095
00096 image<uchar> *im = new image<uchar>(width, height);
00097 for (int i = 0; i < height; i++)
00098 read_packed(imPtr(im, 0, i), width, file);
00099
00100 return im;
00101 }
00102
00103 static void savePBM(image<uchar> *im, const char *name) {
00104 int width = im->width();
00105 int height = im->height();
00106 std::ofstream file(name, std::ios::out | std::ios::binary);
00107
00108 file << "P4\n" << width << " " << height << "\n";
00109 for (int i = 0; i < height; i++)
00110 write_packed(imPtr(im, 0, i), width, file);
00111 }
00112
00113 static image<uchar> *loadPGM(const char *name) {
00114 char buf[BUF_SIZE];
00115
00116
00117 std::ifstream file(name, std::ios::in | std::ios::binary);
00118 pnm_read(file, buf);
00119 if (strncmp(buf, "P5", 2))
00120 throw pnm_error();
00121
00122 pnm_read(file, buf);
00123 int width = atoi(buf);
00124 pnm_read(file, buf);
00125 int height = atoi(buf);
00126
00127 pnm_read(file, buf);
00128 if (atoi(buf) > UCHAR_MAX)
00129 throw pnm_error();
00130
00131
00132 image<uchar> *im = new image<uchar>(width, height);
00133 file.read((char *)imPtr(im, 0, 0), width * height * sizeof(uchar));
00134
00135 return im;
00136 }
00137
00138 static void savePGM(image<uchar> *im, const char *name) {
00139 int width = im->width();
00140 int height = im->height();
00141 std::ofstream file(name, std::ios::out | std::ios::binary);
00142
00143 file << "P5\n" << width << " " << height << "\n" << UCHAR_MAX << "\n";
00144 file.write((char *)imPtr(im, 0, 0), width * height * sizeof(uchar));
00145 }
00146
00147 static image<rgb> *loadPPM(const char *name) {
00148 char buf[BUF_SIZE], doc[BUF_SIZE];
00149
00150
00151 std::ifstream file(name, std::ios::in | std::ios::binary);
00152 pnm_read(file, buf);
00153 if (strncmp(buf, "P6", 2))
00154 throw pnm_error();
00155
00156 pnm_read(file, buf);
00157 int width = atoi(buf);
00158 pnm_read(file, buf);
00159 int height = atoi(buf);
00160
00161 pnm_read(file, buf);
00162 if (atoi(buf) > UCHAR_MAX)
00163 throw pnm_error();
00164
00165
00166 image<rgb> *im = new image<rgb>(width, height);
00167 file.read((char *)imPtr(im, 0, 0), width * height * sizeof(rgb));
00168
00169 return im;
00170 }
00171
00172 static void savePPM(image<rgb> *im, const char *name) {
00173 int width = im->width();
00174 int height = im->height();
00175 std::ofstream file(name, std::ios::out | std::ios::binary);
00176
00177 file << "P6\n" << width << " " << height << "\n" << UCHAR_MAX << "\n";
00178 file.write((char *)imPtr(im, 0, 0), width * height * sizeof(rgb));
00179 }
00180
00181 template <class T>
00182 void load_image(image<T> **im, const char *name) {
00183 char buf[BUF_SIZE];
00184
00185
00186 std::ifstream file(name, std::ios::in | std::ios::binary);
00187 pnm_read(file, buf);
00188 if (strncmp(buf, "VLIB", 9))
00189 throw pnm_error();
00190
00191 pnm_read(file, buf);
00192 int width = atoi(buf);
00193 pnm_read(file, buf);
00194 int height = atoi(buf);
00195
00196
00197 *im = new image<T>(width, height);
00198 file.read((char *)imPtr((*im), 0, 0), width * height * sizeof(T));
00199 }
00200
00201 template <class T>
00202 void save_image(image<T> *im, const char *name) {
00203 int width = im->width();
00204 int height = im->height();
00205 std::ofstream file(name, std::ios::out | std::ios::binary);
00206
00207 file << "VLIB\n" << width << " " << height << "\n";
00208 file.write((char *)imPtr(im, 0, 0), width * height * sizeof(T));
00209 }
00210
00211 #endif