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