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