imageIO.cpp

Go to the documentation of this file.
00001 
00015 #include <fstream>
00016 #include <dlrCommon/byteOrder.h>
00017 #include <dlrComputerVision/imageIO.h>
00018 
00019 namespace {
00020 
00021   void
00022   discardComments(std::istream& inputStream,
00023                   std::istream::char_type commentCharacter)
00024   {
00025     std::istream::char_type inputCharacter;
00026     while(1) {
00027       inputStream >> inputCharacter;
00028       if(inputCharacter == commentCharacter) {
00029         std::string dummyString;
00030         getline(inputStream, dummyString);
00031       } else {
00032         inputStream.putback(inputCharacter);
00033         break;
00034       }
00035     }
00036   }
00037 
00038 
00039   std::string
00040   readComments(std::istream& inputStream,
00041                std::istream::char_type commentCharacter)
00042   {
00043     std::istream::char_type inputCharacter;
00044     std::ostringstream commentStream;
00045     while(1) {
00046       inputStream >> inputCharacter;
00047       if(inputCharacter == commentCharacter) {
00048         std::string dummyString;
00049         getline(inputStream, dummyString);
00050         commentStream << dummyString;
00051       } else {
00052         inputStream.putback(inputCharacter);
00053         break;
00054       }
00055     }
00056     return commentStream.str();
00057   }
00058 
00059 } // Anonymous namespace
00060 
00061 
00062 namespace dlr {
00063 
00064   namespace computerVision {
00065     
00066     Image<GRAY8>
00067     readPGM8(const std::string& fileName)
00068     {
00069       std::string commentString;
00070       return readPGM8(fileName, commentString);
00071     }
00072 
00073   
00074     Image<GRAY8>
00075     readPGM8(const std::string& fileName, std::string& commentString)
00076     {
00077       std::ifstream inputStream(fileName.c_str(), std::ios::binary);
00078       if(!inputStream) {
00079         std::ostringstream message;
00080         message << "Couldn't open input file: " << fileName;
00081         DLR_THROW(IOException, "readPGM8()", message.str().c_str());
00082       }
00083 
00084       // Read the header.
00085       commentString.clear();
00086       std::string magic;
00087       size_t columns;
00088       size_t rows;
00089       long long int imageMax;
00090       inputStream >> magic;
00091       commentString += readComments(inputStream, '#');
00092       inputStream >> columns >> rows;
00093       commentString += readComments(inputStream, '#');
00094       inputStream >> imageMax;
00095 
00096       // Image data starts after the next newline.
00097       std::string dummy;
00098       std::getline(inputStream, dummy);
00099 
00100       // Check for errors.
00101       if(!inputStream) {
00102         std::ostringstream message;
00103         message << "Couldn't read image header from file: " << fileName;
00104         DLR_THROW(IOException, "readPGM8()", message.str().c_str());
00105       }
00106 
00107       // Check that this image will fit in an 8-bit pixel array.
00108       if(imageMax > 255LL) {
00109         std::ostringstream message;
00110         message << "File " << fileName << " has max value of " << imageMax
00111                 << ", which is too big for an 8-bit image.";
00112         DLR_THROW(IOException, "readPGM8()", message.str().c_str());
00113       }
00114 
00115       // Allocate storage space.
00116       Image<GRAY8> newImage(rows, columns);
00117 
00118       // And read the pixels.
00119       if(magic == "P5") {
00120         // Looks like a raw image.
00121         inputStream.read(reinterpret_cast<char*>(newImage.data()),
00122                          newImage.size());
00123       } else if(magic == "P2") {
00124         // Looks like a plain image.
00125         unsigned short interpreter;
00126         for(size_t pixelIndex = 0; pixelIndex < newImage.size(); ++pixelIndex) {
00127           // We can't simply read into the image, since the compiler
00128           // will assume we want the ascii values of the characters in
00129           // the file.
00130           inputStream >> interpreter;
00131           newImage(pixelIndex) =
00132             static_cast<Image<GRAY8>::PixelType>(interpreter);
00133         }
00134       } else {
00135         std::ostringstream message;
00136         message << "Incorrect magic, " << magic << " in file " << fileName
00137                 << ".";
00138         DLR_THROW(IOException, "readPGM8()", message.str().c_str());
00139       }
00140 
00141       // Check for errors.
00142       if(!inputStream) {
00143         std::ostringstream message;
00144         message << "Error reading image data from input file: " << fileName;
00145         DLR_THROW(IOException, "readPGM8()", message.str().c_str());
00146       }
00147     
00148       // All done!
00149       inputStream.close();
00150       return newImage;
00151     }
00152 
00153 
00154     Image<GRAY16>
00155     readPGM16(const std::string& fileName)
00156     {
00157       std::ifstream inputStream(fileName.c_str(), std::ios::binary);
00158       if(!inputStream) {
00159         std::ostringstream message;
00160         message << "Couldn't open input file: " << fileName;
00161         DLR_THROW(IOException, "readPGM16()", message.str().c_str());
00162       }
00163 
00164       // Read the header.
00165       std::string magic;
00166       size_t columns;
00167       size_t rows;
00168       long long int imageMax;
00169       inputStream >> magic;
00170       discardComments(inputStream, '#');
00171       inputStream >> columns >> rows;
00172       discardComments(inputStream, '#');
00173       inputStream >> imageMax;
00174 
00175       // Image data starts after the next newline.
00176       std::string dummy;
00177       std::getline(inputStream, dummy);
00178 
00179       // Check for errors.
00180       if(!inputStream) {
00181         std::ostringstream message;
00182         message << "Couldn't read image header from file: " << fileName;
00183         DLR_THROW(IOException, "readPGM16()", message.str().c_str());
00184       }
00185 
00186       // Check that this image will fit in an 16-bit pixel array.
00187       if(imageMax > 65535LL) {
00188         std::ostringstream message;
00189         message << "File " << fileName << " has max value of " << imageMax
00190                 << ", which is too big for an 16-bit image.";
00191         DLR_THROW(IOException, "readPGM16()", message.str().c_str());
00192       }
00193 
00194       // Allocate storage space.
00195       Image<GRAY16> newImage(rows, columns);
00196 
00197       // And read the pixels.
00198       if(magic == "P5") {
00199         // Looks like a raw image.
00200         if(imageMax <= 255LL) {
00201           // Looks like an 8 bit image.
00202           DLR_THROW(NotImplementedException, "readPGM16()",
00203                     "This routine currently cannot read 8-bit PGMs");
00204         } else {
00205           size_t numberOfBytes = 2 * newImage.size();
00206           inputStream.read(
00207             reinterpret_cast<char*>(newImage.data()), numberOfBytes);
00208           switchByteOrder(newImage.data(), newImage.size(),
00209                           DLR_BIG_ENDIAN, getByteOrder());
00210         }
00211       } else if(magic == "P2") {
00212         // Looks like a plain image.
00213         unsigned short interpreter;
00214         for(size_t pixelIndex = 0; pixelIndex < newImage.size(); ++pixelIndex) {
00215           // We can't simply read into the image, since the compiler
00216           // will assume we want the ascii values of the characters in
00217           // the file.
00218           inputStream >> interpreter;
00219           newImage(pixelIndex) =
00220             static_cast<Image<GRAY16>::PixelType>(interpreter);
00221         }
00222       } else {
00223         std::ostringstream message;
00224         message << "Incorrect magic, " << magic << " in file " << fileName
00225                 << ".";
00226         DLR_THROW(IOException, "readPGM16()", message.str().c_str());
00227       }
00228 
00229       // Check for errors.
00230       if(!inputStream) {
00231         std::ostringstream message;
00232         message << "Error reading image data from input file: " << fileName;
00233         DLR_THROW(IOException, "readPGM16()", message.str().c_str());
00234       }
00235     
00236       // All done!
00237       inputStream.close();
00238       return newImage;
00239     }
00240 
00241 
00242     Image<RGB8>
00243     readPPM8(const std::string& fileName)
00244     {
00245       std::string commentString;
00246       return readPPM8(fileName, commentString);
00247     }
00248       
00249 
00250     Image<RGB8>
00251     readPPM8(const std::string& fileName,
00252              std::string& commentString)
00253     {
00254       std::ifstream inputStream(fileName.c_str(), std::ios::binary);
00255       if(!inputStream) {
00256         std::ostringstream message;
00257         message << "Couldn't open input file: " << fileName;
00258         DLR_THROW(IOException, "readPPM8()", message.str().c_str());
00259       }
00260 
00261       // Read the header.
00262       commentString.clear();
00263       std::string magic;
00264       size_t columns;
00265       size_t rows;
00266       long long int imageMax;
00267       inputStream >> magic;
00268       commentString += readComments(inputStream, '#');
00269       inputStream >> columns >> rows;
00270       commentString += readComments(inputStream, '#');
00271       inputStream >> imageMax;
00272 
00273       // Image data starts after the next newline.
00274       std::string dummy;
00275       std::getline(inputStream, dummy);
00276 
00277       // Check for errors.
00278       if(!inputStream) {
00279         std::ostringstream message;
00280         message << "Couldn't read image header from file: " << fileName;
00281         DLR_THROW(IOException, "readPPM8()", message.str().c_str());
00282       }
00283 
00284       // Check that this image will fit in an 8-bit pixel array.
00285       if(imageMax > 255LL) {
00286         std::ostringstream message;
00287         message << "File " << fileName << " has max value of " << imageMax
00288                 << ", which is too big for an 8-bit image.";
00289         DLR_THROW(IOException, "readPPM8()", message.str().c_str());
00290       }
00291 
00292       // Allocate storage space.
00293       Image<RGB8> newImage(rows, columns);
00294 
00295       // And read the pixels.
00296       if(magic == "P6") {
00297         // Looks like a raw image.
00298         inputStream.read(reinterpret_cast<char*>(newImage.data()),
00299                          newImage.size() * 3);
00300       } else if(magic == "P3") {
00301         // Looks like a plain image.
00302         unsigned short interpreterRed;
00303         unsigned short interpreterGreen;
00304         unsigned short interpreterBlue;
00305         for(size_t pixelIndex = 0; pixelIndex < newImage.size(); ++pixelIndex) {
00306           // We can't simply read into the image, since the compiler
00307           // will assume we want the ascii values of the characters in
00308           // the file.
00309           inputStream >> interpreterRed >> interpreterGreen >> interpreterBlue;
00310           newImage(pixelIndex).red =
00311             static_cast<UnsignedInt8>(interpreterRed);
00312           newImage(pixelIndex).green =
00313             static_cast<UnsignedInt8>(interpreterGreen);
00314           newImage(pixelIndex).blue =
00315             static_cast<UnsignedInt8>(interpreterBlue);
00316         }
00317       } else {
00318         std::ostringstream message;
00319         message << "Incorrect magic, " << magic << " in file " << fileName
00320                 << ".";
00321         DLR_THROW(IOException, "readPPM8()", message.str().c_str());
00322       }
00323 
00324       // Check for errors.
00325       if(!inputStream) {
00326         std::ostringstream message;
00327         message << "Error reading image data from input file: " << fileName;
00328         DLR_THROW(IOException, "readPPM8()", message.str().c_str());
00329       }
00330     
00331       // All done!
00332       inputStream.close();
00333       return newImage;
00334     }
00335 
00336 
00337     void
00338     writePGM8(const std::string& fileName,
00339               const Image<GRAY8>& outputImage,
00340               const std::string& comment)
00341     {
00342       std::ofstream outputStream(fileName.c_str(), std::ios::binary);
00343       if(!outputStream) {
00344         std::ostringstream message;
00345         message << "Couldn't open output file: " << fileName;
00346         DLR_THROW(IOException, "writePGM8()", message.str().c_str());
00347       }
00348 
00349       // Write the header.
00350       outputStream << "P5\n";
00351       if(comment != "") {
00352         outputStream << "# " << comment << "\n";
00353       }
00354       outputStream << outputImage.columns() << " " << outputImage.rows() << "\n"
00355                    << "255\n";
00356 
00357       // Check for errors.
00358       if(!outputStream) {
00359         std::ostringstream message;
00360         message << "Couldn't write image header to file: " << fileName;
00361         DLR_THROW(IOException, "writePGM8()", message.str().c_str());
00362       }
00363 
00364       // And write the pixels.
00365       outputStream.write(reinterpret_cast<const char*>(outputImage.data()),
00366                          outputImage.size());
00367 
00368       // Check for errors.
00369       if(!outputStream) {
00370         std::ostringstream message;
00371         message << "Error writeing image data to output file: " << fileName;
00372         DLR_THROW(IOException, "writePGM8()", message.str().c_str());
00373       }
00374     
00375       // All done!
00376       outputStream.close();
00377     }
00378   
00379 
00380     void
00381     writePGM16(const std::string& fileName,
00382                const Image<GRAY16>& outputImage,
00383                const std::string& comment)
00384     {
00385       std::ofstream outputStream(fileName.c_str(), std::ios::binary);
00386       if(!outputStream) {
00387         std::ostringstream message;
00388         message << "Couldn't open output file: " << fileName;
00389         DLR_THROW(IOException, "writePGM16()", message.str().c_str());
00390       }
00391 
00392       // Write the header.
00393       outputStream << "P5\n";
00394       if(comment != "") {
00395         outputStream << "# " << comment << "\n";
00396       }
00397       outputStream << outputImage.columns() << " " << outputImage.rows() << "\n"
00398                    << "65535\n";
00399 
00400       // Check for errors.
00401       if(!outputStream) {
00402         std::ostringstream message;
00403         message << "Couldn't write image header to file: " << fileName;
00404         DLR_THROW(IOException, "writePGM16()", message.str().c_str());
00405       }
00406 
00407       // And write the pixels.
00408       size_t numberOfElements = outputImage.size();
00409       size_t numberOfBytes =
00410         numberOfElements * sizeof(Image<GRAY16>::value_type);
00411       if(getByteOrder() == DLR_BIG_ENDIAN) {
00412         outputStream.write(
00413           reinterpret_cast<const char*>(outputImage.data()), numberOfBytes);
00414       } else {
00415         char* swabbedData = new char[numberOfBytes];
00416         switchByteOrder(
00417           outputImage.data(), numberOfElements,
00418           reinterpret_cast<Image<GRAY16>::value_type*>(swabbedData),
00419           getByteOrder(), DLR_BIG_ENDIAN);
00420         outputStream.write(swabbedData, numberOfBytes);
00421         delete[] swabbedData;
00422       }
00423 
00424       // Check for errors.
00425       if(!outputStream) {
00426         outputStream.close();
00427         std::ostringstream message;
00428         message << "Error writeing image data to output file: " << fileName;
00429         DLR_THROW(IOException, "writePGM16()", message.str().c_str());
00430       }
00431     
00432       // All done!
00433       outputStream.close();
00434     }
00435   
00436 
00437     void
00438     writePPM8(const std::string& fileName,
00439               const Image<RGB8>& outputImage,
00440               const std::string& comment)
00441     {
00442       std::ofstream outputStream(fileName.c_str(), std::ios::binary);
00443       if(!outputStream) {
00444         std::ostringstream message;
00445         message << "Couldn't open output file: " << fileName;
00446         DLR_THROW(IOException, "writePPM8()", message.str().c_str());
00447       }
00448 
00449       // Write the header.
00450       outputStream << "P6\n";
00451       if(comment != "") {
00452         outputStream << "# " << comment << "\n";
00453       }
00454       outputStream << outputImage.columns() << " " << outputImage.rows() << "\n"
00455                    << "255\n";
00456 
00457       // Check for errors.
00458       if(!outputStream) {
00459         std::ostringstream message;
00460         message << "Couldn't write image header to file: " << fileName;
00461         DLR_THROW(IOException, "writePPM8()", message.str().c_str());
00462       }
00463 
00464       // And write the pixels.
00465       outputStream.write(reinterpret_cast<const char*>(outputImage.data()),
00466                          3 * outputImage.size());
00467 
00468       // Check for errors.
00469       if(!outputStream) {
00470         std::ostringstream message;
00471         message << "Error writeing image data to output file: " << fileName;
00472         DLR_THROW(IOException, "writePPM8()", message.str().c_str());
00473       }
00474     
00475       // All done!
00476       outputStream.close();
00477     }
00478   
00479   } // namespace computerVision    
00480 
00481 } // namespace dlr

Generated on Wed Jun 25 14:34:10 2008 for dlrComputerVision Utility Library by  doxygen 1.5.5