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::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
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
00274 std::string dummy;
00275 std::getline(inputStream, dummy);
00276
00277
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
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
00293 Image<RGB8> newImage(rows, columns);
00294
00295
00296 if(magic == "P6") {
00297
00298 inputStream.read(reinterpret_cast<char*>(newImage.data()),
00299 newImage.size() * 3);
00300 } else if(magic == "P3") {
00301
00302 unsigned short interpreterRed;
00303 unsigned short interpreterGreen;
00304 unsigned short interpreterBlue;
00305 for(size_t pixelIndex = 0; pixelIndex < newImage.size(); ++pixelIndex) {
00306
00307
00308
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
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
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
00350 outputStream << "P5\n";
00351 if(comment != "") {
00352 outputStream << "# " << comment << "\n";
00353 }
00354 outputStream << outputImage.columns() << " " << outputImage.rows() << "\n"
00355 << "255\n";
00356
00357
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
00365 outputStream.write(reinterpret_cast<const char*>(outputImage.data()),
00366 outputImage.size());
00367
00368
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
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
00393 outputStream << "P5\n";
00394 if(comment != "") {
00395 outputStream << "# " << comment << "\n";
00396 }
00397 outputStream << outputImage.columns() << " " << outputImage.rows() << "\n"
00398 << "65535\n";
00399
00400
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
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
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
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
00450 outputStream << "P6\n";
00451 if(comment != "") {
00452 outputStream << "# " << comment << "\n";
00453 }
00454 outputStream << outputImage.columns() << " " << outputImage.rows() << "\n"
00455 << "255\n";
00456
00457
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
00465 outputStream.write(reinterpret_cast<const char*>(outputImage.data()),
00466 3 * outputImage.size());
00467
00468
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
00476 outputStream.close();
00477 }
00478
00479 }
00480
00481 }