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