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 }
00048
00049 }
00050
00051
00052
00053
00054 namespace dlr {
00055
00056 using utilities::writePGM;
00057 using utilities::writePPM;
00058
00059 }
00060
00061
00062
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 }
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
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
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
00157 if(rawFormat) {
00158 privateCode::writeRawPGM(fileName, charBuffer, rows, columns);
00159 } else {
00160 privateCode::writePlainPGM(fileName, charBuffer, rows, columns);
00161 }
00162
00163
00164 privateCode::deletePNMData(charBuffer, imageData);
00165 } else if(bitsPerPixel == 16) {
00166 const unsigned short* shortBuffer;
00167
00168
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
00178 if(rawFormat) {
00179 privateCode::writeRawPGM(fileName, shortBuffer, rows, columns);
00180 } else {
00181 privateCode::writePlainPGM(fileName, shortBuffer, rows, columns);
00182 }
00183
00184
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
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
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
00220 if(rawFormat) {
00221 privateCode::writeRawPPM(fileName, charBuffer, rows, columns);
00222 } else {
00223 privateCode::writePlainPPM(fileName, charBuffer, rows, columns);
00224 }
00225
00226
00227 privateCode::deletePNMData(charBuffer, imageData);
00228 } else {
00229 const unsigned short* shortBuffer;
00230
00231
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
00241 if(rawFormat) {
00242 privateCode::writeRawPPM(fileName, shortBuffer, rows, columns);
00243 } else {
00244 privateCode::writePlainPPM(fileName, shortBuffer, rows, columns);
00245 }
00246
00247
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
00261 Type1* outputBuffer = new Type1[numberOfElements];
00262
00263
00264 for(size_t index0 = 0; index0 < numberOfElements; ++index0) {
00265 outputBuffer[index0] = static_cast<Type1>(sourcePtr[index0]);
00266 }
00267
00268
00269 return outputBuffer;
00270 }
00271
00272
00273 template<class Type0, class Type1>
00274 void
00275 deletePNMData(const Type0* outputBuffer, const Type1* sourcePtr)
00276 {
00277
00278
00279
00280 if(reinterpret_cast<const Type1*>(outputBuffer) == sourcePtr) {
00281 return;
00282 }
00283
00284
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
00294 const int imageMax =
00295 static_cast<int>(std::pow(2.0, 8.0 * sizeof(Type1)) - 0.5);
00296
00297
00298 Type1* outputBuffer = new Type1[numberOfElements];
00299
00300
00301 Type0 maxValue =
00302 *std::max_element(sourcePtr, sourcePtr + numberOfElements);
00303 Type0 minValue =
00304 *std::min_element(sourcePtr, sourcePtr + numberOfElements);
00305
00306
00307 double scaleFactor = 0.0;
00308 if(maxValue != minValue) {
00309 scaleFactor = imageMax / (maxValue - minValue);
00310 }
00311
00312
00313 for(size_t index0 = 0; index0 < numberOfElements; ++index0) {
00314 outputBuffer[index0] = static_cast<Type1>(
00315 (sourcePtr[index0] - minValue) * scaleFactor);
00316 }
00317
00318
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
00331 const int imageMax =
00332 static_cast<int>(std::pow(2.0, 8.0 * sizeof(Type)) - 0.5);
00333
00334
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
00343 outputStream << "P5\n"
00344 << columns << " " << rows << "\n"
00345 << imageMax << "\n";
00346
00347
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
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
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
00396 const int imageMax =
00397 static_cast<int>(std::pow(2.0, 8.0 * sizeof(Type)) - 0.5);
00398
00399
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
00408 outputStream << "P6\n"
00409 << columns << " " << rows << "\n"
00410 << imageMax << "\n";
00411
00412
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
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
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
00460 const int imageMax =
00461 static_cast<int>(std::pow(2.0, 8.0 * sizeof(Type)) - 0.5);
00462
00463
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
00472 outputStream << "P2\n"
00473 << columns << " " << rows << "\n"
00474 << imageMax << "\n";
00475
00476
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
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
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
00505 const int imageMax =
00506 static_cast<int>(std::pow(2.0, 8.0 * sizeof(Type)) - 0.5);
00507
00508
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
00517 outputStream << "P3\n"
00518 << columns << " " << rows << "\n"
00519 << imageMax << "\n";
00520
00521
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
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
00540 outputStream.close();
00541 }
00542
00543 }
00545
00546 }
00547
00548 }
00549
00550 #endif // #ifndef _DLR_IMAGEIO_H_