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::ifstream inputStream(fileName.c_str(), std::ios::binary);
00246       if(!inputStream) {
00247         std::ostringstream message;
00248         message << "Couldn't open input file: " << fileName;
00249         DLR_THROW(IOException, "readPPM8()", message.str().c_str());
00250       }
00251 
00252       // Read the header.
00253       std::string magic;
00254       size_t columns;
00255       size_t rows;
00256       long long int imageMax;
00257       inputStream >> magic;
00258       discardComments(inputStream, '#');
00259       inputStream >> columns >> rows;
00260       discardComments(inputStream, '#');
00261       inputStream >> imageMax;
00262 
00263       // Image data starts after the next newline.
00264       std::string dummy;
00265       std::getline(inputStream, dummy);
00266 
00267       // Check for errors.
00268       if(!inputStream) {
00269         std::ostringstream message;
00270         message << "Couldn't read image header from file: " << fileName;
00271         DLR_THROW(IOException, "readPPM8()", message.str().c_str());
00272       }
00273 
00274       // Check that this image will fit in an 8-bit pixel array.
00275       if(imageMax > 255LL) {
00276         std::ostringstream message;
00277         message << "File " << fileName << " has max value of " << imageMax
00278                 << ", which is too big for an 8-bit image.";
00279         DLR_THROW(IOException, "readPPM8()", message.str().c_str());
00280       }
00281 
00282       // Allocate storage space.
00283       Image<RGB8> newImage(rows, columns);
00284 
00285       // And read the pixels.
00286       if(magic == "P6") {
00287         // Looks like a raw image.
00288         inputStream.read(reinterpret_cast<char*>(newImage.data()),
00289                          newImage.size() * 3);
00290       } else if(magic == "P3") {
00291         // Looks like a plain image.
00292         unsigned short interpreterRed;
00293         unsigned short interpreterGreen;
00294         unsigned short interpreterBlue;
00295         for(size_t pixelIndex = 0; pixelIndex < newImage.size(); ++pixelIndex) {
00296           // We can't simply read into the image, since the compiler
00297           // will assume we want the ascii values of the characters in
00298           // the file.
00299           inputStream >> interpreterRed >> interpreterGreen >> interpreterBlue;
00300           newImage(pixelIndex).red =
00301             static_cast<UnsignedInt8>(interpreterRed);
00302           newImage(pixelIndex).green =
00303             static_cast<UnsignedInt8>(interpreterGreen);
00304           newImage(pixelIndex).blue =
00305             static_cast<UnsignedInt8>(interpreterBlue);
00306         }
00307       } else {
00308         std::ostringstream message;
00309         message << "Incorrect magic, " << magic << " in file " << fileName
00310                 << ".";
00311         DLR_THROW(IOException, "readPPM8()", message.str().c_str());
00312       }
00313 
00314       // Check for errors.
00315       if(!inputStream) {
00316         std::ostringstream message;
00317         message << "Error reading image data from input file: " << fileName;
00318         DLR_THROW(IOException, "readPPM8()", message.str().c_str());
00319       }
00320     
00321       // All done!
00322       inputStream.close();
00323       return newImage;
00324     }
00325 
00326 
00327     void
00328     writePGM8(const std::string& fileName,
00329               const Image<GRAY8>& outputImage,
00330               const std::string& comment)
00331     {
00332       std::ofstream outputStream(fileName.c_str(), std::ios::binary);
00333       if(!outputStream) {
00334         std::ostringstream message;
00335         message << "Couldn't open output file: " << fileName;
00336         DLR_THROW(IOException, "writePGM8()", message.str().c_str());
00337       }
00338 
00339       // Write the header.
00340       outputStream << "P5\n";
00341       if(comment != "") {
00342         outputStream << "# " << comment << "\n";
00343       }
00344       outputStream << outputImage.columns() << " " << outputImage.rows() << "\n"
00345                    << "255\n";
00346 
00347       // Check for errors.
00348       if(!outputStream) {
00349         std::ostringstream message;
00350         message << "Couldn't write image header to file: " << fileName;
00351         DLR_THROW(IOException, "writePGM8()", message.str().c_str());
00352       }
00353 
00354       // And write the pixels.
00355       outputStream.write(reinterpret_cast<const char*>(outputImage.data()),
00356                          outputImage.size());
00357 
00358       // Check for errors.
00359       if(!outputStream) {
00360         std::ostringstream message;
00361         message << "Error writeing image data to output file: " << fileName;
00362         DLR_THROW(IOException, "writePGM8()", message.str().c_str());
00363       }
00364     
00365       // All done!
00366       outputStream.close();
00367     }
00368   
00369 
00370     void
00371     writePGM16(const std::string& fileName,
00372                const Image<GRAY16>& outputImage,
00373                const std::string& comment)
00374     {
00375       std::ofstream outputStream(fileName.c_str(), std::ios::binary);
00376       if(!outputStream) {
00377         std::ostringstream message;
00378         message << "Couldn't open output file: " << fileName;
00379         DLR_THROW(IOException, "writePGM16()", message.str().c_str());
00380       }
00381 
00382       // Write the header.
00383       outputStream << "P5\n";
00384       if(comment != "") {
00385         outputStream << "# " << comment << "\n";
00386       }
00387       outputStream << outputImage.columns() << " " << outputImage.rows() << "\n"
00388                    << "65535\n";
00389 
00390       // Check for errors.
00391       if(!outputStream) {
00392         std::ostringstream message;
00393         message << "Couldn't write image header to file: " << fileName;
00394         DLR_THROW(IOException, "writePGM16()", message.str().c_str());
00395       }
00396 
00397       // And write the pixels.
00398       size_t numberOfElements = outputImage.size();
00399       size_t numberOfBytes =
00400         numberOfElements * sizeof(Image<GRAY16>::value_type);
00401       if(getByteOrder() == DLR_BIG_ENDIAN) {
00402         outputStream.write(
00403           reinterpret_cast<const char*>(outputImage.data()), numberOfBytes);
00404       } else {
00405         char* swabbedData = new char[numberOfBytes];
00406         switchByteOrder(
00407           outputImage.data(), numberOfElements,
00408           reinterpret_cast<Image<GRAY16>::value_type*>(swabbedData),
00409           getByteOrder(), DLR_BIG_ENDIAN);
00410         outputStream.write(swabbedData, numberOfBytes);
00411         delete[] swabbedData;
00412       }
00413 
00414       // Check for errors.
00415       if(!outputStream) {
00416         outputStream.close();
00417         std::ostringstream message;
00418         message << "Error writeing image data to output file: " << fileName;
00419         DLR_THROW(IOException, "writePGM16()", message.str().c_str());
00420       }
00421     
00422       // All done!
00423       outputStream.close();
00424     }
00425   
00426 
00427     void
00428     writePPM8(const std::string& fileName,
00429               const Image<RGB8>& outputImage,
00430               const std::string& comment)
00431     {
00432       std::ofstream outputStream(fileName.c_str(), std::ios::binary);
00433       if(!outputStream) {
00434         std::ostringstream message;
00435         message << "Couldn't open output file: " << fileName;
00436         DLR_THROW(IOException, "writePPM8()", message.str().c_str());
00437       }
00438 
00439       // Write the header.
00440       outputStream << "P6\n";
00441       if(comment != "") {
00442         outputStream << "# " << comment << "\n";
00443       }
00444       outputStream << outputImage.columns() << " " << outputImage.rows() << "\n"
00445                    << "255\n";
00446 
00447       // Check for errors.
00448       if(!outputStream) {
00449         std::ostringstream message;
00450         message << "Couldn't write image header to file: " << fileName;
00451         DLR_THROW(IOException, "writePPM8()", message.str().c_str());
00452       }
00453 
00454       // And write the pixels.
00455       outputStream.write(reinterpret_cast<const char*>(outputImage.data()),
00456                          3 * outputImage.size());
00457 
00458       // Check for errors.
00459       if(!outputStream) {
00460         std::ostringstream message;
00461         message << "Error writeing image data to output file: " << fileName;
00462         DLR_THROW(IOException, "writePPM8()", message.str().c_str());
00463       }
00464     
00465       // All done!
00466       outputStream.close();
00467     }
00468   
00469   } // namespace computerVision    
00470 
00471 } // namespace dlr

Generated on Mon Jul 9 20:34:03 2007 for dlrLibs Utility Libraries by  doxygen 1.5.2