00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042 #ifdef __hpux // prevent int32 clash (model.h/tiff.h)
00043 #define _INT32
00044 #endif
00045
00046 #include <stdlib.h>
00047 #include <stdio.h>
00048
00049 #include "OSGConfig.h"
00050
00051 #include "OSGTIFImageFileType.h"
00052
00053 #ifdef OSG_WITH_TIF
00054 #include <tiffio.h>
00055 #endif
00056 #include <OSGLog.h>
00057
00058 #ifndef OSG_DO_DOC
00059 # ifdef OSG_WITH_TIF
00060 # define OSG_TIF_ARG(ARG) ARG
00061 # else
00062 # define OSG_TIF_ARG(ARG)
00063 # endif
00064 #else
00065 # define OSG_TIF_ARG(ARG) ARG
00066 #endif
00067
00068
00069 OSG_USING_NAMESPACE
00070
00071
00087 static void warningHandler (const char *module, const char *fmt, va_list ap)
00088 {
00089 Char8 buffer[4096];
00090
00091 #ifdef OSG_HAS_VSNPRINTF
00092 vsnprintf(buffer, sizeof(buffer) - 1, fmt, ap);
00093 #else
00094 vsprintf(buffer, fmt, ap);
00095 #endif
00096
00097 FWARNING (("TiffLib: %s;%s\n", module ? module : "Mod", buffer));
00098 }
00099
00100 static void errorHandler (const char *module, const char *fmt, va_list ap)
00101 {
00102 Char8 buffer[4096];
00103
00104 #ifdef OSG_HAS_VSNPRINTF
00105 vsnprintf(buffer, sizeof(buffer) - 1, fmt, ap);
00106 #else
00107 vsprintf(buffer, fmt, ap);
00108 #endif
00109
00110 FFATAL (("TiffLib: %s;%s\n", module ? module : "Mod", buffer));
00111 }
00112
00113
00114
00115 static const Char8 *suffixArray[] = {
00116 "tif", "tiff"
00117 };
00118
00119 TIFImageFileType TIFImageFileType:: _the("tiff",
00120 suffixArray, sizeof(suffixArray),
00121 OSG_READ_SUPPORTED |
00122 OSG_WRITE_SUPPORTED);
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00156 TIFImageFileType& TIFImageFileType::the (void)
00157 {
00158 static bool initTIFFLib = true;
00159
00160 #ifdef OSG_WITH_TIF
00161
00162 if (initTIFFLib)
00163 {
00164 initTIFFLib = false;
00165
00166 TIFFSetWarningHandler(&warningHandler);
00167 TIFFSetErrorHandler(&errorHandler);
00168 }
00169
00170 #endif
00171
00172 return _the;
00173 }
00174
00175
00176
00177
00178
00179
00180
00185 bool TIFImageFileType::read( ImagePtr &OSG_TIF_ARG(image),
00186 const Char8 *OSG_TIF_ARG(fileName))
00187 {
00188 bool valid = false;
00189
00190 #ifdef OSG_WITH_TIF
00191 TIFF *in = TIFFOpen(fileName, "r");
00192 UChar8 *data = 0, *line = 0, *dest;
00193 UInt32 w, h, u, v;
00194 UInt16 bpp;
00195 Char8 errorMessage[1024];
00196 UInt16 *sampleinfo;
00197 UInt16 extrasamples;
00198 UInt16 si;
00199 UInt16 red, green, blue, alpha;
00200
00201 if(in)
00202 {
00203 TIFFGetField(in, TIFFTAG_IMAGEWIDTH, &w);
00204
00205 TIFFGetField(in, TIFFTAG_IMAGELENGTH, &h);
00206
00207 TIFFGetFieldDefaulted(in, TIFFTAG_SAMPLESPERPIXEL, &bpp);
00208
00209 if(bpp == 4)
00210 {
00211 TIFFGetFieldDefaulted(in, TIFFTAG_EXTRASAMPLES, &extrasamples,
00212 &sampleinfo);
00213
00214 if(sampleinfo && sampleinfo[0] == EXTRASAMPLE_UNSPECIFIED)
00215 {
00216 si = EXTRASAMPLE_ASSOCALPHA;
00217 TIFFSetField(in, TIFFTAG_EXTRASAMPLES, 1, &si);
00218 }
00219 }
00220
00221 data = new UChar8[w * h * 4];
00222 if(TIFFRGBAImageOK(in, errorMessage) &&
00223 TIFFReadRGBAImage(in, w, h, (uint32 *) data, 1))
00224 valid = true;
00225 else
00226 {
00227 SWARNING << "Tiff reader failed: " << errorMessage << std::endl;
00228 valid = false;
00229 }
00230
00231 if(valid)
00232 {
00233 Image::PixelFormat type = osg::Image::OSG_INVALID_PF;
00234 switch(bpp)
00235 {
00236 case 1:
00237 type = Image::OSG_L_PF;
00238 break;
00239 case 2:
00240 type = Image::OSG_LA_PF;
00241 break;
00242 case 3:
00243 type = Image::OSG_RGB_PF;
00244 break;
00245 case 4:
00246 type = Image::OSG_RGBA_PF;
00247 break;
00248 }
00249
00250 image->set(type, w, h);
00251 dest = image->getData();
00252
00253 #if defined(__linux) || defined(_WIN32)
00254 red = 0;
00255 green = 1;
00256 blue = 2;
00257 alpha = 3;
00258
00259 #else
00260 red = 3;
00261 green = 2;
00262 blue = 1;
00263 alpha = 0;
00264 #endif
00265 for(v = 0; v < h; v++)
00266 {
00267 line = data + ((v) * (w * 4));
00268 for(u = 0; u < w; u++)
00269 {
00270 switch(bpp)
00271 {
00272 case 4:
00273 *dest++ = line[red];
00274 *dest++ = line[green];
00275 *dest++ = line[blue];
00276 *dest++ = line[alpha];
00277 break;
00278 case 3:
00279 *dest++ = line[red];
00280 *dest++ = line[green];
00281 *dest++ = line[blue];
00282 break;
00283 case 2:
00284 *dest++ = line[red];
00285 *dest++ = line[green];
00286 break;
00287 case 1:
00288 *dest++ = line[red];
00289 break;
00290 }
00291
00292 line += 4;
00293 }
00294 }
00295
00296 TIFFClose(in);
00297 delete[] data;
00298 data = 0;
00299 }
00300 }
00301
00302 #else
00303 SWARNING <<
00304 getMimeType() <<
00305 " read is not compiled into the current binary " <<
00306 std::endl;
00307 #endif
00308 return valid;
00309 }
00310
00311
00316 bool TIFImageFileType::write(const ImagePtr &OSG_TIF_ARG(image),
00317 const Char8 *OSG_TIF_ARG(fileName))
00318 {
00319 bool retCode = false;
00320
00321 #ifdef OSG_WITH_TIF
00322
00323 if(image->getDimension() < 1 || image->getDimension() > 2)
00324 {
00325 FWARNING(("TIFImageFileType::write: invalid dimension %d!\n",
00326 image->getDimension()));
00327 return false;
00328 }
00329
00330 TIFF *out = TIFFOpen(fileName, "w");
00331 int lineSize = image->getWidth() * image->getBpp();
00332 int photometric = 0, samplesPerPixel = 0;
00333 const UChar8 *data;
00334 int row;
00335
00336
00337 switch(image->getBpp())
00338 {
00339 case 1:
00340 samplesPerPixel = 1;
00341 photometric = PHOTOMETRIC_MINISBLACK;
00342 break;
00343 case 2:
00344 samplesPerPixel = 2;
00345 photometric = PHOTOMETRIC_MINISBLACK;
00346 break;
00347 case 3:
00348 samplesPerPixel = 3;
00349 photometric = PHOTOMETRIC_RGB;
00350 break;
00351 case 4:
00352 samplesPerPixel = 4;
00353 photometric = PHOTOMETRIC_RGB;
00354 break;
00355 }
00356
00357 if(out)
00358 {
00359 TIFFSetField(out, TIFFTAG_IMAGEWIDTH, image->getWidth());
00360 TIFFSetField(out, TIFFTAG_IMAGELENGTH, image->getHeight());
00361 TIFFSetField(out, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);
00362 TIFFSetField(out, TIFFTAG_SAMPLESPERPIXEL, samplesPerPixel);
00363 TIFFSetField(out, TIFFTAG_BITSPERSAMPLE, 8);
00364 TIFFSetField(out, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
00365 TIFFSetField(out, TIFFTAG_PHOTOMETRIC, photometric);
00366 TIFFSetField(out, TIFFTAG_COMPRESSION, COMPRESSION_NONE);
00367 TIFFSetField(out, TIFFTAG_ROWSPERSTRIP, TIFFDefaultStripSize(out, 0));
00368
00369 for(row = 0; row < image->getHeight(); row++)
00370 {
00371 data = image->getData() + ((image->getHeight() - row - 1) * lineSize);
00372 if(TIFFWriteScanline(out,
00373 (tdata_t) const_cast<UChar8 *>(data),
00374 row,
00375 0) < 0)
00376 break;
00377 }
00378
00379 TIFFClose(out);
00380 retCode = true;
00381 }
00382
00383 #else
00384 SWARNING <<
00385 getMimeType() <<
00386 " write is not compiled into the current binary " <<
00387 std::endl;
00388 #endif
00389 return retCode;
00390 }
00391
00392 bool TIFImageFileType::validateHeader( const Char8 *fileName, bool &implemented)
00393 {
00394 implemented = true;
00395
00396 if(fileName == NULL)
00397 return false;
00398
00399 FILE *file = fopen(fileName, "rb");
00400 if(file == NULL)
00401 return false;
00402
00403 std::string magic;
00404 magic.resize(2);
00405 fread((void *) &magic[0], 2, 1, file);
00406 fclose(file);
00407
00408 if(magic == "MM" || magic == "II")
00409 {
00410 return true;
00411 }
00412
00413 return false;
00414 }
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00434
00438 TIFImageFileType::TIFImageFileType(const Char8 *mimeType,
00439 const Char8 *suffixArray[],
00440 UInt16 suffixByteCount,
00441 UInt32 flags) :
00442 ImageFileType(mimeType,suffixArray, suffixByteCount, flags)
00443 {
00444 the();
00445 }
00446
00447
00451 TIFImageFileType::TIFImageFileType(const TIFImageFileType &obj) :
00452 ImageFileType(obj)
00453 {
00454 the();
00455 }
00456
00457
00461 TIFImageFileType::~TIFImageFileType(void)
00462 {
00463 return;
00464 }