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 }
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
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
00097 std::string dummy;
00098 std::getline(inputStream, dummy);
00099
00100
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
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
00116 Image<GRAY8> newImage(rows, columns);
00117
00118
00119 if(magic == "P5") {
00120
00121 inputStream.read(reinterpret_cast<char*>(newImage.data()),
00122 newImage.size());
00123 } else if(magic == "P2") {
00124
00125 unsigned short interpreter;
00126 for(size_t pixelIndex = 0; pixelIndex < newImage.size(); ++pixelIndex) {
00127
00128
00129
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
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
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
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
00176 std::string dummy;
00177 std::getline(inputStream, dummy);
00178
00179
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
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
00195 Image<GRAY16> newImage(rows, columns);
00196
00197
00198 if(magic == "P5") {
00199
00200 if(imageMax <= 255LL) {
00201
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
00213 unsigned short interpreter;
00214 for(size_t pixelIndex = 0; pixelIndex < newImage.size(); ++pixelIndex) {
00215
00216
00217
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
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
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
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
00264 std::string dummy;
00265 std::getline(inputStream, dummy);
00266
00267
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
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
00283 Image<RGB8> newImage(rows, columns);
00284
00285
00286 if(magic == "P6") {
00287
00288 inputStream.read(reinterpret_cast<char*>(newImage.data()),
00289 newImage.size() * 3);
00290 } else if(magic == "P3") {
00291
00292 unsigned short interpreterRed;
00293 unsigned short interpreterGreen;
00294 unsigned short interpreterBlue;
00295 for(size_t pixelIndex = 0; pixelIndex < newImage.size(); ++pixelIndex) {
00296
00297
00298
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
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
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
00340 outputStream << "P5\n";
00341 if(comment != "") {
00342 outputStream << "# " << comment << "\n";
00343 }
00344 outputStream << outputImage.columns() << " " << outputImage.rows() << "\n"
00345 << "255\n";
00346
00347
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
00355 outputStream.write(reinterpret_cast<const char*>(outputImage.data()),
00356 outputImage.size());
00357
00358
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
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
00383 outputStream << "P5\n";
00384 if(comment != "") {
00385 outputStream << "# " << comment << "\n";
00386 }
00387 outputStream << outputImage.columns() << " " << outputImage.rows() << "\n"
00388 << "65535\n";
00389
00390
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
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
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
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
00440 outputStream << "P6\n";
00441 if(comment != "") {
00442 outputStream << "# " << comment << "\n";
00443 }
00444 outputStream << outputImage.columns() << " " << outputImage.rows() << "\n"
00445 << "255\n";
00446
00447
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
00455 outputStream.write(reinterpret_cast<const char*>(outputImage.data()),
00456 3 * outputImage.size());
00457
00458
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
00466 outputStream.close();
00467 }
00468
00469 }
00470
00471 }