imageIO.cpp

Go to the documentation of this file.
00001 
00015 #include <fstream>
00016 
00017 #include <png.h>
00018 
00019 #include <dlrCommon/byteOrder.h>
00020 #include <dlrComputerVision/imageIO.h>
00021 
00022 namespace {
00023 
00024   void
00025   discardComments(std::istream& inputStream,
00026                   std::istream::char_type commentCharacter)
00027   {
00028     std::istream::char_type inputCharacter;
00029     while(1) {
00030       inputStream >> inputCharacter;
00031       if(inputCharacter == commentCharacter) {
00032         std::string dummyString;
00033         getline(inputStream, dummyString);
00034       } else {
00035         inputStream.putback(inputCharacter);
00036         break;
00037       }
00038     }
00039   }
00040 
00041 
00042   std::string
00043   readComments(std::istream& inputStream,
00044                std::istream::char_type commentCharacter)
00045   {
00046     std::istream::char_type inputCharacter;
00047     std::ostringstream commentStream;
00048     while(1) {
00049       inputStream >> inputCharacter;
00050       if(inputCharacter == commentCharacter) {
00051         std::string dummyString;
00052         getline(inputStream, dummyString);
00053         commentStream << dummyString;
00054       } else {
00055         inputStream.putback(inputCharacter);
00056         break;
00057       }
00058     }
00059     return commentStream.str();
00060   }
00061 
00062 } // Anonymous namespace
00063 
00064 
00065 namespace dlr {
00066 
00067   namespace computerVision {
00068 
00069 
00070 #if 0
00071     
00072     // Constructor.
00073     ImageReader::
00074     ImageReader()
00075     {
00076       // Empty.
00077     }
00078       
00079       
00080     // Destructor.
00081     ImageReader::
00082     ~ImageReader()
00083     {
00084       // Empty.
00085     }
00086 
00087 
00088     void
00089     ImageReader::
00090     readFile(std::string const& fileName)
00091     {
00092 
00093     }
00094 
00095 
00096     ImageFormat
00097     ImageReader::
00098     getNativeFormat()
00099     {
00100       return GRAY8;
00101     }
00102 
00103 #endif
00104     
00105     Image<GRAY8>
00106     readPGM8(const std::string& fileName)
00107     {
00108       std::string commentString;
00109       return readPGM8(fileName, commentString);
00110     }
00111 
00112   
00113     Image<GRAY8>
00114     readPGM8(const std::string& fileName, std::string& commentString)
00115     {
00116       std::ifstream inputStream(fileName.c_str(), std::ios::binary);
00117       if(!inputStream) {
00118         std::ostringstream message;
00119         message << "Couldn't open input file: " << fileName;
00120         DLR_THROW(IOException, "readPGM8()", message.str().c_str());
00121       }
00122 
00123       // Read the header.
00124       commentString.clear();
00125       std::string magic;
00126       size_t columns;
00127       size_t rows;
00128       long long int imageMax;
00129       inputStream >> magic;
00130       commentString += readComments(inputStream, '#');
00131       inputStream >> columns >> rows;
00132       commentString += readComments(inputStream, '#');
00133       inputStream >> imageMax;
00134 
00135       // Image data starts after the next newline.
00136       std::string dummy;
00137       std::getline(inputStream, dummy);
00138 
00139       // Check for errors.
00140       if(!inputStream) {
00141         std::ostringstream message;
00142         message << "Couldn't read image header from file: " << fileName;
00143         DLR_THROW(IOException, "readPGM8()", message.str().c_str());
00144       }
00145 
00146       // Check that this image will fit in an 8-bit pixel array.
00147       if(imageMax > 255LL) {
00148         std::ostringstream message;
00149         message << "File " << fileName << " has max value of " << imageMax
00150                 << ", which is too big for an 8-bit image.";
00151         DLR_THROW(IOException, "readPGM8()", message.str().c_str());
00152       }
00153 
00154       // Allocate storage space.
00155       Image<GRAY8> newImage(rows, columns);
00156 
00157       // And read the pixels.
00158       if(magic == "P5") {
00159         // Looks like a raw image.
00160         inputStream.read(reinterpret_cast<char*>(newImage.data()),
00161                          newImage.size());
00162       } else if(magic == "P2") {
00163         // Looks like a plain image.
00164         unsigned short interpreter;
00165         for(size_t pixelIndex = 0; pixelIndex < newImage.size(); ++pixelIndex) {
00166           // We can't simply read into the image, since the compiler
00167           // will assume we want the ascii values of the characters in
00168           // the file.
00169           inputStream >> interpreter;
00170           newImage(pixelIndex) =
00171             static_cast<Image<GRAY8>::PixelType>(interpreter);
00172         }
00173       } else {
00174         std::ostringstream message;
00175         message << "Incorrect magic, " << magic << " in file " << fileName
00176                 << ".";
00177         DLR_THROW(IOException, "readPGM8()", message.str().c_str());
00178       }
00179 
00180       // Check for errors.
00181       if(!inputStream) {
00182         std::ostringstream message;
00183         message << "Error reading image data from input file: " << fileName;
00184         DLR_THROW(IOException, "readPGM8()", message.str().c_str());
00185       }
00186     
00187       // All done!
00188       inputStream.close();
00189       return newImage;
00190     }
00191 
00192 
00193     Image<GRAY16>
00194     readPGM16(const std::string& fileName)
00195     {
00196       std::ifstream inputStream(fileName.c_str(), std::ios::binary);
00197       if(!inputStream) {
00198         std::ostringstream message;
00199         message << "Couldn't open input file: " << fileName;
00200         DLR_THROW(IOException, "readPGM16()", message.str().c_str());
00201       }
00202 
00203       // Read the header.
00204       std::string magic;
00205       size_t columns;
00206       size_t rows;
00207       long long int imageMax;
00208       inputStream >> magic;
00209       discardComments(inputStream, '#');
00210       inputStream >> columns >> rows;
00211       discardComments(inputStream, '#');
00212       inputStream >> imageMax;
00213 
00214       // Image data starts after the next newline.
00215       std::string dummy;
00216       std::getline(inputStream, dummy);
00217 
00218       // Check for errors.
00219       if(!inputStream) {
00220         std::ostringstream message;
00221         message << "Couldn't read image header from file: " << fileName;
00222         DLR_THROW(IOException, "readPGM16()", message.str().c_str());
00223       }
00224 
00225       // Check that this image will fit in an 16-bit pixel array.
00226       if(imageMax > 65535LL) {
00227         std::ostringstream message;
00228         message << "File " << fileName << " has max value of " << imageMax
00229                 << ", which is too big for an 16-bit image.";
00230         DLR_THROW(IOException, "readPGM16()", message.str().c_str());
00231       }
00232 
00233       // Allocate storage space.
00234       Image<GRAY16> newImage(rows, columns);
00235 
00236       // And read the pixels.
00237       if(magic == "P5") {
00238         // Looks like a raw image.
00239         if(imageMax <= 255LL) {
00240           // Looks like an 8 bit image.
00241           DLR_THROW(NotImplementedException, "readPGM16()",
00242                     "This routine currently cannot read 8-bit PGMs");
00243         } else {
00244           size_t numberOfBytes = 2 * newImage.size();
00245           inputStream.read(
00246             reinterpret_cast<char*>(newImage.data()), numberOfBytes);
00247           switchByteOrder(newImage.data(), newImage.size(),
00248                           DLR_BIG_ENDIAN, getByteOrder());
00249         }
00250       } else if(magic == "P2") {
00251         // Looks like a plain image.
00252         unsigned short interpreter;
00253         for(size_t pixelIndex = 0; pixelIndex < newImage.size(); ++pixelIndex) {
00254           // We can't simply read into the image, since the compiler
00255           // will assume we want the ascii values of the characters in
00256           // the file.
00257           inputStream >> interpreter;
00258           newImage(pixelIndex) =
00259             static_cast<Image<GRAY16>::PixelType>(interpreter);
00260         }
00261       } else {
00262         std::ostringstream message;
00263         message << "Incorrect magic, " << magic << " in file " << fileName
00264                 << ".";
00265         DLR_THROW(IOException, "readPGM16()", message.str().c_str());
00266       }
00267 
00268       // Check for errors.
00269       if(!inputStream) {
00270         std::ostringstream message;
00271         message << "Error reading image data from input file: " << fileName;
00272         DLR_THROW(IOException, "readPGM16()", message.str().c_str());
00273       }
00274     
00275       // All done!
00276       inputStream.close();
00277       return newImage;
00278     }
00279 
00280 
00281     Image<RGB8>
00282     readPPM8(const std::string& fileName)
00283     {
00284       std::string commentString;
00285       return readPPM8(fileName, commentString);
00286     }
00287       
00288 
00289     Image<RGB8>
00290     readPPM8(const std::string& fileName,
00291              std::string& commentString)
00292     {
00293       std::ifstream inputStream(fileName.c_str(), std::ios::binary);
00294       if(!inputStream) {
00295         std::ostringstream message;
00296         message << "Couldn't open input file: " << fileName;
00297         DLR_THROW(IOException, "readPPM8()", message.str().c_str());
00298       }
00299 
00300       // Read the header.
00301       commentString.clear();
00302       std::string magic;
00303       size_t columns;
00304       size_t rows;
00305       long long int imageMax;
00306       inputStream >> magic;
00307       commentString += readComments(inputStream, '#');
00308       inputStream >> columns >> rows;
00309       commentString += readComments(inputStream, '#');
00310       inputStream >> imageMax;
00311 
00312       // Image data starts after the next newline.
00313       std::string dummy;
00314       std::getline(inputStream, dummy);
00315 
00316       // Check for errors.
00317       if(!inputStream) {
00318         std::ostringstream message;
00319         message << "Couldn't read image header from file: " << fileName;
00320         DLR_THROW(IOException, "readPPM8()", message.str().c_str());
00321       }
00322 
00323       // Check that this image will fit in an 8-bit pixel array.
00324       if(imageMax > 255LL) {
00325         std::ostringstream message;
00326         message << "File " << fileName << " has max value of " << imageMax
00327                 << ", which is too big for an 8-bit image.";
00328         DLR_THROW(IOException, "readPPM8()", message.str().c_str());
00329       }
00330 
00331       // Allocate storage space.
00332       Image<RGB8> newImage(rows, columns);
00333 
00334       // And read the pixels.
00335       if(magic == "P6") {
00336         // Looks like a raw image.
00337         inputStream.read(reinterpret_cast<char*>(newImage.data()),
00338                          newImage.size() * 3);
00339       } else if(magic == "P3") {
00340         // Looks like a plain image.
00341         unsigned short interpreterRed;
00342         unsigned short interpreterGreen;
00343         unsigned short interpreterBlue;
00344         for(size_t pixelIndex = 0; pixelIndex < newImage.size(); ++pixelIndex) {
00345           // We can't simply read into the image, since the compiler
00346           // will assume we want the ascii values of the characters in
00347           // the file.
00348           inputStream >> interpreterRed >> interpreterGreen >> interpreterBlue;
00349           newImage(pixelIndex).red =
00350             static_cast<UnsignedInt8>(interpreterRed);
00351           newImage(pixelIndex).green =
00352             static_cast<UnsignedInt8>(interpreterGreen);
00353           newImage(pixelIndex).blue =
00354             static_cast<UnsignedInt8>(interpreterBlue);
00355         }
00356       } else {
00357         std::ostringstream message;
00358         message << "Incorrect magic, " << magic << " in file " << fileName
00359                 << ".";
00360         DLR_THROW(IOException, "readPPM8()", message.str().c_str());
00361       }
00362 
00363       // Check for errors.
00364       if(!inputStream) {
00365         std::ostringstream message;
00366         message << "Error reading image data from input file: " << fileName;
00367         DLR_THROW(IOException, "readPPM8()", message.str().c_str());
00368       }
00369     
00370       // All done!
00371       inputStream.close();
00372       return newImage;
00373     }
00374 
00375 
00376     void
00377     writePGM8(const std::string& fileName,
00378               const Image<GRAY8>& outputImage,
00379               const std::string& comment)
00380     {
00381       std::ofstream outputStream(fileName.c_str(), std::ios::binary);
00382       if(!outputStream) {
00383         std::ostringstream message;
00384         message << "Couldn't open output file: " << fileName;
00385         DLR_THROW(IOException, "writePGM8()", message.str().c_str());
00386       }
00387 
00388       // Write the header.
00389       outputStream << "P5\n";
00390       if(comment != "") {
00391         outputStream << "# " << comment << "\n";
00392       }
00393       outputStream << outputImage.columns() << " " << outputImage.rows() << "\n"
00394                    << "255\n";
00395 
00396       // Check for errors.
00397       if(!outputStream) {
00398         std::ostringstream message;
00399         message << "Couldn't write image header to file: " << fileName;
00400         DLR_THROW(IOException, "writePGM8()", message.str().c_str());
00401       }
00402 
00403       // And write the pixels.
00404       outputStream.write(reinterpret_cast<const char*>(outputImage.data()),
00405                          outputImage.size());
00406 
00407       // Check for errors.
00408       if(!outputStream) {
00409         std::ostringstream message;
00410         message << "Error writeing image data to output file: " << fileName;
00411         DLR_THROW(IOException, "writePGM8()", message.str().c_str());
00412       }
00413     
00414       // All done!
00415       outputStream.close();
00416     }
00417   
00418 
00419     void
00420     writePGM16(const std::string& fileName,
00421                const Image<GRAY16>& outputImage,
00422                const std::string& comment)
00423     {
00424       std::ofstream outputStream(fileName.c_str(), std::ios::binary);
00425       if(!outputStream) {
00426         std::ostringstream message;
00427         message << "Couldn't open output file: " << fileName;
00428         DLR_THROW(IOException, "writePGM16()", message.str().c_str());
00429       }
00430 
00431       // Write the header.
00432       outputStream << "P5\n";
00433       if(comment != "") {
00434         outputStream << "# " << comment << "\n";
00435       }
00436       outputStream << outputImage.columns() << " " << outputImage.rows() << "\n"
00437                    << "65535\n";
00438 
00439       // Check for errors.
00440       if(!outputStream) {
00441         std::ostringstream message;
00442         message << "Couldn't write image header to file: " << fileName;
00443         DLR_THROW(IOException, "writePGM16()", message.str().c_str());
00444       }
00445 
00446       // And write the pixels.
00447       size_t numberOfElements = outputImage.size();
00448       size_t numberOfBytes =
00449         numberOfElements * sizeof(Image<GRAY16>::value_type);
00450       if(getByteOrder() == DLR_BIG_ENDIAN) {
00451         outputStream.write(
00452           reinterpret_cast<const char*>(outputImage.data()), numberOfBytes);
00453       } else {
00454         char* swabbedData = new char[numberOfBytes];
00455         switchByteOrder(
00456           outputImage.data(), numberOfElements,
00457           reinterpret_cast<Image<GRAY16>::value_type*>(swabbedData),
00458           getByteOrder(), DLR_BIG_ENDIAN);
00459         outputStream.write(swabbedData, numberOfBytes);
00460         delete[] swabbedData;
00461       }
00462 
00463       // Check for errors.
00464       if(!outputStream) {
00465         outputStream.close();
00466         std::ostringstream message;
00467         message << "Error writeing image data to output file: " << fileName;
00468         DLR_THROW(IOException, "writePGM16()", message.str().c_str());
00469       }
00470     
00471       // All done!
00472       outputStream.close();
00473     }
00474   
00475 
00476     void
00477     writePPM8(const std::string& fileName,
00478               const Image<RGB8>& outputImage,
00479               const std::string& comment)
00480     {
00481       std::ofstream outputStream(fileName.c_str(), std::ios::binary);
00482       if(!outputStream) {
00483         std::ostringstream message;
00484         message << "Couldn't open output file: " << fileName;
00485         DLR_THROW(IOException, "writePPM8()", message.str().c_str());
00486       }
00487 
00488       // Write the header.
00489       outputStream << "P6\n";
00490       if(comment != "") {
00491         outputStream << "# " << comment << "\n";
00492       }
00493       outputStream << outputImage.columns() << " " << outputImage.rows() << "\n"
00494                    << "255\n";
00495 
00496       // Check for errors.
00497       if(!outputStream) {
00498         std::ostringstream message;
00499         message << "Couldn't write image header to file: " << fileName;
00500         DLR_THROW(IOException, "writePPM8()", message.str().c_str());
00501       }
00502 
00503       // And write the pixels.
00504       outputStream.write(reinterpret_cast<const char*>(outputImage.data()),
00505                          3 * outputImage.size());
00506 
00507       // Check for errors.
00508       if(!outputStream) {
00509         std::ostringstream message;
00510         message << "Error writeing image data to output file: " << fileName;
00511         DLR_THROW(IOException, "writePPM8()", message.str().c_str());
00512       }
00513     
00514       // All done!
00515       outputStream.close();
00516     }
00517 
00518 
00519 #if HAVE_LIBPNG
00520 
00521     Image<GRAY8>
00522     readPNG8(const std::string& fileName,
00523              std::string& commentString)
00524     {
00525       // This code is heavily in debt to example.c from the libpng 1.2.1
00526       // distribition, which carries the following header comment:
00527       // /* example.c - an example of using libpng
00528       //  * Last changed in libpng 1.2.1 December 7, 2001.
00529       //  * This file has been placed in the public domain by the authors.
00530       //  * Maintained 1998-2001 Glenn Randers-Pehrson
00531       //  * Maintained 1996, 1997 Andreas Dilger)
00532       //  * Written 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
00533       //  */
00534 
00535       Image<GRAY8> result;
00536 
00537       // We'll check eight bytes of magic at the beginning of the file
00538       // to make sure it's actually a png image.
00539       const size_t pngSignatureSize = 8;
00540 
00541       FILE *fp = fopen(fileName.c_str(), "rb");
00542       if (fp == 0) {
00543         DLR_THROW(dlr::IOException, "dlr::computerVision::readPng8()",
00544                   "Couldn't open input file.");
00545       }
00546 
00547       // Be sure to clean up the open file.
00548       try {
00549 
00550         // Read and check the png magic to see if we have an actual
00551         // png image.
00552         unsigned char header[pngSignatureSize + 1];
00553         if(fread(header, 1, pngSignatureSize, fp) != pngSignatureSize) {
00554           DLR_THROW(IOException, "dlr::computerVision::readPng8()",
00555                     "Couldn't read png signature from file.");
00556         }
00557         if(png_sig_cmp(header, 0, pngSignatureSize) != 0) {
00558           DLR_THROW(IOException, "dlr::computerVision::readPng8()",
00559                     "Fiel doesn't seem to be a PNG image.");
00560         }
00561         
00562         // Create and initialize the png_struct with the default stderr
00563         // and longjump error functions.
00564         png_structp pngPtr = png_create_read_struct(
00565           PNG_LIBPNG_VER_STRING, 0, 0, 0);
00566         if(pngPtr == 0) {
00567           DLR_THROW(dlr::RunTimeException, "dlr::computerVision::readPng8()",
00568                     "Couldn't initialize png_structp.");
00569         }
00570 
00571         // This variable is just to let us choreograph nicely with libpng
00572         // cleanup functions.
00573         png_infop* infoPtrPtrForCleanup = png_infopp_NULL;
00574 
00575         // Be sure to clean up pngPtr (and later, infoPtr).
00576         try {
00577 
00578           // Allocate/initialize the memory for image information.
00579           png_infop infoPtr = png_create_info_struct(pngPtr);
00580           if (infoPtr == 0) {
00581             DLR_THROW(RunTimeException, "dlr::computerVision::readPng8()",
00582                       "Couldn't initialize png_infop.");
00583           }
00584           infoPtrPtrForCleanup = &infoPtr;
00585        
00586           // Set error handling in case libpng calls longjmp().
00587           if(setjmp(png_jmpbuf(pngPtr))) {
00588             DLR_THROW(dlr::IOException, "dlr::computerVision::readPng8()",
00589                       "Trouble reading from file.");
00590           }
00591         
00592           // Set up the input control.
00593           png_init_io(pngPtr, fp);
00594 
00595           // Let libpng know that we've already checked some magic.
00596           png_set_sig_bytes(pngPtr, pngSignatureSize);
00597           
00598           // Read entire image into pngPtr.
00599           png_read_png(pngPtr, infoPtr, PNG_TRANSFORM_IDENTITY, png_voidp_NULL);
00600 
00601           // Find out about our image.
00602           png_uint_32 width, height;
00603           int bitDepth, colorType, interlaceType;
00604           int compressionType, filterMethod;
00605           png_get_IHDR(pngPtr, infoPtr, &width, &height, &bitDepth, &colorType,
00606                        &interlaceType, &compressionType, &filterMethod);
00607           if(bitDepth != 8) {
00608             DLR_THROW(IOException, "dlr::computerVision::readPng8()",
00609                       "Image file is not 8 bit.");
00610           }
00611           if(colorType != PNG_COLOR_TYPE_GRAY) {
00612             DLR_THROW(IOException, "dlr::computerVision::readPng8()",
00613                       "Can currently only handle grayscale images.");
00614           }
00615           if(interlaceType != PNG_INTERLACE_NONE) {
00616             DLR_THROW(IOException, "dlr::computerVision::readPng8()",
00617                       "Can currently only handle non-interlaced images.");
00618           }
00619 
00620           // Copy image and return.
00621           result.reinit(height, width);
00622           png_bytep* rowPointers = png_get_rows(pngPtr, infoPtr);
00623           for(size_t rowIndex = 0; rowIndex < height; ++rowIndex) {
00624             result.getRow(rowIndex).copy(rowPointers[rowIndex]);
00625           }
00626 
00627         } catch(...) {
00628           png_destroy_read_struct(
00629             &pngPtr, infoPtrPtrForCleanup, png_infopp_NULL);
00630           throw;
00631         }
00632         
00633         // clean up after the read, and free any memory allocated.
00634         png_destroy_read_struct(&pngPtr, infoPtrPtrForCleanup, png_infopp_NULL);
00635 
00636       } catch(...) {
00637         fclose(fp);
00638         throw;
00639       }
00640       fclose(fp);
00641 
00642       return result;
00643     }
00644 
00645     
00646     void
00647     writePNG8(const std::string& fileName,
00648               const Image<GRAY8>& outputImage,
00649               const std::string& comment)
00650     {
00651       // This code is heavily in debt to example.c from the libpng 1.2.1
00652       // distribition, which carries the following header comment:
00653       // /* example.c - an example of using libpng
00654       //  * Last changed in libpng 1.2.1 December 7, 2001.
00655       //  * This file has been placed in the public domain by the authors.
00656       //  * Maintained 1998-2001 Glenn Randers-Pehrson
00657       //  * Maintained 1996, 1997 Andreas Dilger)
00658       //  * Written 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
00659       //  */
00660 
00661       FILE* fp = fopen(fileName.c_str(), "wb");
00662       if (fp == 0) {
00663         DLR_THROW(dlr::IOException, "ImageIO::writePng()",
00664                   "Couldn't open output file.");
00665       }
00666 
00667       // Make sure we clean up open FILE.
00668       try {
00669 
00670         // Create and initialize the png_struct with the default stderr and
00671         // longjump error handler functions.
00672         png_structp pngPtr = png_create_write_struct(
00673           PNG_LIBPNG_VER_STRING, 0, 0, 0);
00674         if (pngPtr == 0) {
00675           DLR_THROW(dlr::RunTimeException, "ImageIO::writePng()",
00676                     "Couldn't initialize png_structp.");
00677         }
00678 
00679         // This variable is just to let us choreograph nicely with libpng
00680         // cleanup functions.
00681         png_infop* infoPtrPtrForCleanup = png_infopp_NULL;
00682 
00683         // Make sure we clean up pngPtr (and eventually infoPtr).
00684         try { 
00685 
00686           // We'll need a place to record details (colorspace, etc.)
00687           // about the image.
00688           png_infop infoPtr = png_create_info_struct(pngPtr);
00689           if (infoPtr == 0) {
00690             DLR_THROW(dlr::RunTimeException, "ImageIO::writePng()",
00691                       "Couldn't initialize png_infop.");
00692           }
00693           infoPtrPtrForCleanup = &infoPtr;
00694        
00695           // Set error handling in case libpng calls longjmp().
00696           if(setjmp(png_jmpbuf(pngPtr))) {
00697             // If we get here, we had a problem reading the file
00698             DLR_THROW(dlr::IOException, "ImageIO::writePng()",
00699                       "Trouble reading from file.");
00700           }
00701 
00702           // Set up the output control.
00703           png_init_io(pngPtr, fp);
00704 
00705           // Note(xxx): Just in case we need it...
00706           // png_set_compression_level(pngPtr, Z_BEST_COMPRESSION);
00707 
00708           // Prepare for writing.
00709           png_set_IHDR(
00710             pngPtr, infoPtr, outputImage.columns(), outputImage.rows(),
00711             sizeof(ImageFormatTraits<GRAY8>::PixelType) * 8,
00712             PNG_COLOR_TYPE_GRAY, PNG_INTERLACE_NONE,
00713             PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
00714          
00715      
00716           // xxx Fill in png structure here.
00717           png_bytep* rowPointers = (png_bytep*)png_malloc(
00718             pngPtr, outputImage.rows() * png_sizeof(png_bytep));
00719           if(rowPointers == 0) {
00720             DLR_THROW(dlr::RunTimeException, "ImageIO::writePng()",
00721                       "Couldn't allocate row pointers.");
00722           }
00723 
00724           // Be sure to free rowPointers.
00725           try {
00726             for(size_t rowIndex = 0; rowIndex < outputImage.rows();
00727                 ++rowIndex) {
00728               rowPointers[rowIndex] = const_cast<unsigned char*>(
00729                 outputImage.getRow(rowIndex).data());
00730             }
00731             png_set_rows(pngPtr, infoPtr, rowPointers);
00732             png_write_png(
00733               pngPtr, infoPtr, PNG_TRANSFORM_IDENTITY, png_voidp_NULL);
00734           } catch(...) {
00735             png_free(pngPtr, rowPointers);
00736           }
00737           png_free(pngPtr, rowPointers);
00738 
00739           /* If you png_malloced a palette, free it here (don't free
00740              infoPtr->palette, as recommended in versions 1.0.5m and
00741              earlier of this example; if libpng mallocs infoPtr->palette,
00742              libpng will free it).  If you allocated it with malloc()
00743              instead of png_malloc(), use free() instead of
00744              png_free(). */
00745           // png_free(pngPtr, palette); xxx;
00746           // palette=NULL;
00747 
00748         } catch(...) {
00749           png_destroy_write_struct(&pngPtr, infoPtrPtrForCleanup);
00750           throw;
00751         }
00752        
00753         /* clean up after the write, and free any memory allocated */
00754         png_destroy_write_struct(&pngPtr, infoPtrPtrForCleanup);
00755 
00756       } catch(...) {
00757         fclose(fp);
00758         throw;
00759       }
00760 
00761       fclose(fp);
00762 
00763     }
00764 
00765 #endif /* #if HAVE_LIBPNG */
00766     
00767   } // namespace computerVision    
00768 
00769 } // namespace dlr

Generated on Wed Nov 25 12:15:05 2009 for dlrComputerVision Utility Library by  doxygen 1.5.8