dlrUtilities/imageIO.h

Go to the documentation of this file.
00001 
00015 #ifndef _DLR_IMAGEIO_H_
00016 #define _DLR_IMAGEIO_H_
00017 
00018 #include <string>
00019 #include <dlrCommon/byteOrder.h>
00020 
00021 namespace dlr {
00022 
00023   namespace utilities {
00024 
00025     template<class Type>
00026     void
00027     writePGM(const std::string& fileName,
00028              const Type* imageData,
00029              const size_t rows,
00030              const size_t columns,
00031              bool normalize=false,
00032              bool rawFormat=true,
00033              int bitsPerPixel=8);
00034 
00035   
00036     template<class Type>
00037     void
00038     writePPM(const std::string& fileName,
00039              const Type* imageData,
00040              const size_t rows,
00041              const size_t columns,
00042              bool normalize=false,
00043              bool rawFormat=true,
00044              int bitsPerPixel=8);
00045 
00046 
00047   } // namespace utilities
00048 
00049 } // namespace dlr
00050 
00051 
00052 /* ======= Declarations to maintain compatibility with legacy code. ======= */
00053 
00054 namespace dlr {
00055 
00056   using utilities::writePGM;
00057   using utilities::writePPM;
00058   
00059 } // namespace dlr
00060 
00061 
00062 /* ================ Function definitions follow ================ */
00063 
00064 #include <cmath>
00065 #include <fstream>
00066 #include <sstream>
00067 #include <dlrCommon/exception.h>
00068 
00069 namespace dlr {
00070 
00071   namespace utilities {
00072 
00074     namespace privateCode {
00075 
00076       template<class Type0, class Type1>
00077       const Type1*
00078       copyPNMData(const Type0* sourcePtr, size_t numberOfElements);
00079 
00080   
00081       template<class Type0, class Type1>
00082       void
00083       deletePNMData(const Type0* outputBuffer, const Type1* sourcePtr);
00084 
00085   
00086       template<class Type0, class Type1>
00087       const Type1*
00088       normalizePNMData(const Type0* sourcePtr, size_t numberOfElements);
00089 
00090   
00091       template<class Type>
00092       void
00093       writeRawPGM(const std::string& fileName,
00094                   const Type* imageData,
00095                   const size_t rows,
00096                   const size_t columns);
00097 
00098   
00099       template<class Type>
00100       void
00101       writeRawPPM(const std::string& fileName,
00102                   const Type* imageData,
00103                   const size_t rows,
00104                   const size_t columns);
00105 
00106   
00107       template<class Type>
00108       void
00109       writePlainPGM(const std::string& fileName,
00110                     const Type* imageData,
00111                     const size_t rows,
00112                     const size_t columns);
00113 
00114       
00115       template<class Type>
00116       void
00117       writePlainPPM(const std::string& fileName,
00118                     const Type* imageData,
00119                     const size_t rows,
00120                     const size_t columns);
00121 
00122     } // namespace privateCode
00124     
00125 
00126     template<class Type>
00127     void
00128     writePGM(const std::string& fileName,
00129              const Type* imageData,
00130              const size_t rows,
00131              const size_t columns,
00132              bool normalize,
00133              bool rawFormat,
00134              int bitsPerPixel)
00135     {
00136       // Check arguments.
00137       if((bitsPerPixel != 8) && (bitsPerPixel != 16)) {
00138         DLR_THROW(ValueException, "writePGM(...)",
00139                   "Argument bitsPerPixel must be either 8 or 16.");
00140       }
00141 
00142       size_t numberOfElements = rows * columns;
00143       if(bitsPerPixel == 8) {
00144         const unsigned char* charBuffer;
00145 
00146         // Normalize if necessary.
00147         if(normalize) {
00148           charBuffer = privateCode::normalizePNMData<Type, UnsignedInt8>(
00149             imageData, numberOfElements);
00150 
00151         } else {
00152           charBuffer = privateCode::copyPNMData<Type, UnsignedInt8>(
00153             imageData, numberOfElements);
00154         }
00155       
00156         // Dispatch to the appropriate IO routine.
00157         if(rawFormat) {
00158           privateCode::writeRawPGM(fileName, charBuffer, rows, columns);
00159         } else {
00160           privateCode::writePlainPGM(fileName, charBuffer, rows, columns);
00161         }
00162 
00163         // And clean up.
00164         privateCode::deletePNMData(charBuffer, imageData);
00165       } else if(bitsPerPixel == 16) {
00166         const unsigned short* shortBuffer;
00167 
00168         // Normalize if necessary.
00169         if(normalize) {
00170           shortBuffer = privateCode::normalizePNMData<Type, UnsignedInt16>(
00171             imageData, numberOfElements);
00172         } else {
00173           shortBuffer = privateCode::copyPNMData<Type, UnsignedInt16>(
00174             imageData, numberOfElements);
00175         }
00176       
00177         // Dispatch to the appropriate IO routine.
00178         if(rawFormat) {
00179           privateCode::writeRawPGM(fileName, shortBuffer, rows, columns);
00180         } else {
00181           privateCode::writePlainPGM(fileName, shortBuffer, rows, columns);
00182         }
00183 
00184         // And clean up.
00185         privateCode::deletePNMData(shortBuffer, imageData);
00186       }
00187     }
00188 
00189 
00190     template<class Type>
00191     void
00192     writePPM(const std::string& fileName,
00193              const Type* imageData,
00194              const size_t rows,
00195              const size_t columns,
00196              bool normalize,
00197              bool rawFormat,
00198              int bitsPerPixel)
00199     {
00200       // Check arguments.
00201       if((bitsPerPixel != 8) && (bitsPerPixel != 16)) {
00202         DLR_THROW(ValueException, "writePGM(...)",
00203                   "Argument bitsPerPixel must be either 8 or 16.");
00204       }
00205 
00206       size_t numberOfElements = rows * columns * 3;
00207       if(bitsPerPixel == 8) {
00208         const unsigned char* charBuffer;
00209 
00210         // Normalize if necessary.
00211         if(normalize) {
00212           charBuffer = privateCode::normalizePNMData<Type, UnsignedInt8>(
00213             imageData, numberOfElements);
00214         } else {
00215           charBuffer = privateCode::copyPNMData<Type, UnsignedInt8>(
00216             imageData, numberOfElements);
00217         }
00218       
00219         // Dispatch to the appropriate IO routine.
00220         if(rawFormat) {
00221           privateCode::writeRawPPM(fileName, charBuffer, rows, columns);
00222         } else {
00223           privateCode::writePlainPPM(fileName, charBuffer, rows, columns);
00224         }
00225 
00226         // And clean up.
00227         privateCode::deletePNMData(charBuffer, imageData);
00228       } else {
00229         const unsigned short* shortBuffer;
00230 
00231         // Normalize if necessary.
00232         if(normalize) {
00233           shortBuffer = privateCode::normalizePNMData<Type, UnsignedInt16>(
00234             imageData, numberOfElements);
00235         } else {
00236           shortBuffer = privateCode::copyPNMData<Type, UnsignedInt16>(
00237             imageData, numberOfElements);
00238         }
00239       
00240         // Dispatch to the appropriate IO routine.
00241         if(rawFormat) {
00242           privateCode::writeRawPPM(fileName, shortBuffer, rows, columns);
00243         } else {
00244           privateCode::writePlainPPM(fileName, shortBuffer, rows, columns);
00245         }
00246 
00247         // And clean up.
00248         privateCode::deletePNMData(shortBuffer, imageData);
00249       }
00250     }
00251 
00252 
00254     namespace privateCode {
00255 
00256       template<class Type0, class Type1>
00257       const Type1*
00258       copyPNMData(const Type0* sourcePtr, size_t numberOfElements)
00259       {
00260         // Make a buffer to hold the normalized image data.
00261         Type1* outputBuffer = new Type1[numberOfElements];
00262 
00263         // Convert to Type1.
00264         for(size_t index0 = 0; index0 < numberOfElements; ++index0) {
00265           outputBuffer[index0] = static_cast<Type1>(sourcePtr[index0]);
00266         }
00267 
00268         // All done.
00269         return outputBuffer;
00270       }
00271   
00272 
00273       template<class Type0, class Type1>
00274       void
00275       deletePNMData(const Type0* outputBuffer, const Type1* sourcePtr)
00276       {
00277         // Eventually, we might make copyPNMData() simply return the input
00278         // pointer if the input pointer has the right type.  Check to make
00279         // sure that didn't happen.
00280         if(reinterpret_cast<const Type1*>(outputBuffer) == sourcePtr) {
00281           return;
00282         }
00283 
00284         // On with the deletion!
00285         delete[] outputBuffer;
00286       }
00287 
00288   
00289       template<class Type0, class Type1>
00290       const Type1*
00291       normalizePNMData(const Type0* sourcePtr, size_t numberOfElements)
00292       {
00293         // Compute the largest acceptable value for the target type.
00294         const int imageMax =
00295           static_cast<int>(std::pow(2.0, 8.0 * sizeof(Type1)) - 0.5);
00296 
00297         // Make a buffer to hold the normalized image data.
00298         Type1* outputBuffer = new Type1[numberOfElements];
00299 
00300         // Figure out the range of pixel values.
00301         Type0 maxValue =
00302           *std::max_element(sourcePtr, sourcePtr + numberOfElements);
00303         Type0 minValue =
00304           *std::min_element(sourcePtr, sourcePtr + numberOfElements);
00305 
00306         // Try to avoid dividing by zero.
00307         double scaleFactor = 0.0;
00308         if(maxValue != minValue) {
00309           scaleFactor = imageMax / (maxValue - minValue);      
00310         }
00311 
00312         // Do the actual normalization.
00313         for(size_t index0 = 0; index0 < numberOfElements; ++index0) {
00314           outputBuffer[index0] = static_cast<Type1>(
00315             (sourcePtr[index0] - minValue) * scaleFactor);
00316         }
00317 
00318         // All done.
00319         return outputBuffer;
00320       }
00321 
00322   
00323       template<class Type>
00324       void
00325       writeRawPGM(const std::string& fileName,
00326                   const Type* imageData,
00327                   const size_t rows,
00328                   const size_t columns)
00329       {
00330         // Compute the largest acceptable value for the target type.
00331         const int imageMax =
00332           static_cast<int>(std::pow(2.0, 8.0 * sizeof(Type)) - 0.5);
00333     
00334         // Open the file.
00335         std::ofstream outputStream(fileName.c_str(), std::ios::binary);
00336         if(!outputStream) {
00337           std::ostringstream message;
00338           message << "Couldn't open output file: " << fileName;
00339           DLR_THROW(IOException, "writeRawPGM()", message.str().c_str());
00340         }
00341 
00342         // Write the header.
00343         outputStream << "P5\n"
00344                      << columns << " " << rows << "\n"
00345                      << imageMax << "\n";
00346 
00347         // Write the image data.
00348         size_t numberOfElements = rows * columns;
00349         if(sizeof(Type) == 1) {
00350           outputStream.write(
00351             (char*)imageData, static_cast<std::streamsize>(numberOfElements));
00352         } else if(sizeof(Type) == 2) {
00353           size_t numberOfBytes = 2 * numberOfElements;
00354           if(getByteOrder() != DLR_BIG_ENDIAN) {
00355             char* swabbedData = new char[numberOfBytes];
00356             switchByteOrder(
00357               imageData, numberOfElements,
00358               reinterpret_cast<Type*>(swabbedData),
00359               getByteOrder(), DLR_BIG_ENDIAN);
00360             outputStream.write(
00361               swabbedData, static_cast<std::streamsize>(numberOfBytes));
00362             delete[] swabbedData;
00363           } else {
00364             outputStream.write(
00365               (char*)imageData, static_cast<std::streamsize>(numberOfBytes));
00366           }
00367         } else {
00368           outputStream.close();
00369           std::ostringstream message;
00370           message << "Can't write a pgm with " << sizeof(Type)
00371                   << "-byte values.";
00372           DLR_THROW(ValueException, "writeRawPGM()", message.str().c_str());
00373         }      
00374         
00375         // Check for errors.
00376         if(!outputStream) {
00377           outputStream.close();
00378           std::ostringstream message;
00379           message << "Error writing to open output file: " << fileName;
00380           DLR_THROW(IOException, "writeRawPGM()", message.str().c_str());
00381         }
00382     
00383         // All done!
00384         outputStream.close();
00385       }
00386 
00387   
00388       template<class Type>
00389       void
00390       writeRawPPM(const std::string& fileName,
00391                   const Type* imageData,
00392                   const size_t rows,
00393                   const size_t columns)
00394       {
00395         // Compute the largest acceptable value for the target type.
00396         const int imageMax =
00397           static_cast<int>(std::pow(2.0, 8.0 * sizeof(Type)) - 0.5);
00398     
00399         // Open the file.
00400         std::ofstream outputStream(fileName.c_str(), std::ios::binary);
00401         if(!outputStream) {
00402           std::ostringstream message;
00403           message << "Couldn't open output file: " << fileName;
00404           DLR_THROW(IOException, "writeRawPPM()", message.str().c_str());
00405         }
00406 
00407         // Write the header.
00408         outputStream << "P6\n"
00409                      << columns << " " << rows << "\n"
00410                      << imageMax << "\n";
00411 
00412         // Write the image data.
00413         size_t numberOfElements = rows * columns * 3;
00414         if(sizeof(Type) == 1) {
00415           outputStream.write(
00416             (char*)imageData, static_cast<std::streamsize>(numberOfElements));
00417         } else if(sizeof(Type) == 2) {
00418           size_t numberOfBytes = 2 * numberOfElements;
00419           if(getByteOrder() != DLR_BIG_ENDIAN) {
00420             char* swabbedData = new char[numberOfBytes];
00421             switchByteOrder(
00422               imageData, numberOfElements,
00423               reinterpret_cast<Type*>(swabbedData),
00424               getByteOrder(), DLR_BIG_ENDIAN);
00425             outputStream.write(
00426               swabbedData, static_cast<std::streamsize>(numberOfBytes));
00427             delete[] swabbedData;
00428           } else {
00429             outputStream.write(
00430               (char*)imageData, static_cast<std::streamsize>(numberOfBytes));
00431           }
00432         } else {
00433           outputStream.close();
00434           std::ostringstream message;
00435           message << "Can't write a ppm with " << sizeof(Type)
00436                   << "-byte values.";
00437           DLR_THROW(ValueException, "writeRawPPM()", message.str().c_str());
00438         }      
00439         
00440         // Check for errors.
00441         if(!outputStream) {
00442           std::ostringstream message;
00443           message << "Error writing to open output file: " << fileName;
00444           DLR_THROW(IOException, "writeRawPPM()", message.str().c_str());
00445         }
00446     
00447         // All done!
00448         outputStream.close();
00449       }
00450 
00451   
00452       template<class Type>
00453       void
00454       writePlainPGM(const std::string& fileName,
00455                     const Type* imageData,
00456                     const size_t rows,
00457                     const size_t columns)
00458       {
00459         // Compute the largest acceptable value for the target type.
00460         const int imageMax =
00461           static_cast<int>(std::pow(2.0, 8.0 * sizeof(Type)) - 0.5);
00462     
00463         // Open the file.
00464         std::ofstream outputStream(fileName.c_str());
00465         if(!outputStream) {
00466           std::ostringstream message;
00467           message << "Couldn't open output file: " << fileName;
00468           DLR_THROW(IOException, "writePlainPGM()", message.str().c_str());
00469         }
00470 
00471         // Write the header.
00472         outputStream << "P2\n"
00473                      << columns << " " << rows << "\n"
00474                      << imageMax << "\n";
00475 
00476         // Write the image data.
00477         for(size_t row = 0; row < rows; ++row) {
00478           for(size_t column = 0; column < columns; ++column) {
00479             outputStream << static_cast<int>(*imageData) << " ";
00480             ++imageData;
00481           }
00482           outputStream << "\n";
00483         }
00484 
00485         // Check for errors.
00486         if(!outputStream) {
00487           std::ostringstream message;
00488           message << "Error writing to open output file: " << fileName;
00489           DLR_THROW(IOException, "writePlainPGM()", message.str().c_str());
00490         }
00491 
00492         // All done!
00493         outputStream.close();
00494       }
00495     
00496 
00497       template<class Type>
00498       void
00499       writePlainPPM(const std::string& fileName,
00500                     const Type* imageData,
00501                     const size_t rows,
00502                     const size_t columns)
00503       {
00504         // Compute the largest acceptable value for the target type.
00505         const int imageMax =
00506           static_cast<int>(std::pow(2.0, 8.0 * sizeof(Type)) - 0.5);
00507     
00508         // Open the file.
00509         std::ofstream outputStream(fileName.c_str());
00510         if(!outputStream) {
00511           std::ostringstream message;
00512           message << "Couldn't open output file: " << fileName;
00513           DLR_THROW(IOException, "writePlainPPM()", message.str().c_str());
00514         }
00515 
00516         // Write the header.
00517         outputStream << "P3\n"
00518                      << columns << " " << rows << "\n"
00519                      << imageMax << "\n";
00520 
00521         // Write the image data.
00522         for(size_t row = 0; row < rows; ++row) {
00523           for(size_t column = 0; column < columns; ++column) {
00524             outputStream << static_cast<int>(*imageData) << " "
00525                          << static_cast<int>(*(imageData + 1)) << " "
00526                          << static_cast<int>(*(imageData + 3)) << " ";
00527             imageData += 3;
00528           }
00529           outputStream << "\n";
00530         }
00531 
00532         // Check for errors.
00533         if(!outputStream) {
00534           std::ostringstream message;
00535           message << "Error writing to open output file: " << fileName;
00536           DLR_THROW(IOException, "writePlainPPM()", message.str().c_str());
00537         }
00538 
00539         // All done!
00540         outputStream.close();
00541       }
00542 
00543     } // namespace privateCode
00545 
00546   } // namespace utilities
00547   
00548 } // namespace dlr
00549 
00550 #endif // #ifndef _DLR_IMAGEIO_H_

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