1 /*---------------------------------------------------------------------------*\
5 * Copyright (C) 2000-2002 by the OpenSG Forum *
9 * contact: dirk@opensg.org, gerrit.voss@vossg.org, jbehr@zgdv.de *
11 \*---------------------------------------------------------------------------*/
12 /*---------------------------------------------------------------------------*\
15 * This library is free software; you can redistribute it and/or modify it *
16 * under the terms of the GNU Library General Public License as published *
17 * by the Free Software Foundation, version 2. *
19 * This library is distributed in the hope that it will be useful, but *
20 * WITHOUT ANY WARRANTY; without even the implied warranty of *
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
22 * Library General Public License for more details. *
24 * You should have received a copy of the GNU Library General Public *
25 * License along with this library; if not, write to the Free Software *
26 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
28 \*---------------------------------------------------------------------------*/
29 /*---------------------------------------------------------------------------*\
37 \*---------------------------------------------------------------------------*/
38 //-------------------------------
40 //-------------------------------
42 #ifdef __hpux // prevent int32 clash (model.h/tiff.h)
49 #include "OSGConfig.h"
51 #include "OSGTIFImageFileType.h"
60 # define OSG_TIF_ARG(ARG) ARG
62 # define OSG_TIF_ARG(ARG)
65 # define OSG_TIF_ARG(ARG) ARG
68 // Static Class Varible implementations:
69 static const OSG::Char8
*suffixArray
[] =
77 /*! \class TIFImageFileType
79 Image File Type to read/write and store/restore Image objects as
80 TIF (tif/tiff suffix) data.
82 To be able to load TIFF images you need the IJG TIFF library,
83 (check the Prerequisites page on www.opensg.org).
84 The lib comes with all Linux distributions.
86 You have to --enable-tif in the configure line to enable
93 static tsize_t
isReadProc(thandle_t fd
, tdata_t buf
, tsize_t size
)
95 std::istream
*is
= reinterpret_cast<std::istream
*>(fd
);
96 is
->read(static_cast<char*>(buf
), size
);
100 static tsize_t
osReadProc(thandle_t fd
, tdata_t buf
, tsize_t size
)
105 static tsize_t
isWriteProc(thandle_t fd
, tdata_t buf
, tsize_t size
)
110 static tsize_t
osWriteProc(thandle_t fd
, tdata_t buf
, tsize_t size
)
112 std::ostream
*os
= reinterpret_cast<std::ostream
*>(fd
);
113 os
->write(static_cast<char*>(buf
), size
);
114 return os
->good() ? size
: 0;
117 static toff_t
isSeekProc(thandle_t fd
, toff_t off
, int i
)
119 std::istream
*is
= reinterpret_cast<std::istream
*>(fd
);
123 is
->seekg(off
, std::ios::beg
);
126 is
->seekg(off
, std::ios::cur
);
129 is
->seekg(off
, std::ios::end
);
135 static toff_t
osSeekProc(thandle_t fd
, toff_t off
, int i
)
137 std::ostream
*os
= reinterpret_cast<std::ostream
*>(fd
);
141 os
->seekp(off
, std::ios::beg
);
144 os
->seekp(off
, std::ios::cur
);
147 os
->seekp(off
, std::ios::end
);
153 static int closeProc(thandle_t fd
)
155 return 0; // no action necessary
158 static toff_t
isSizeProc(thandle_t fd
)
160 std::istream
*is
= reinterpret_cast<std::istream
*>(fd
);
161 std::ios::pos_type pos
= is
->tellg();
162 is
->seekg(0, std::ios::end
);
163 std::ios::pos_type size
= is
->tellg();
164 is
->seekg(pos
, std::ios::beg
);
168 static toff_t
osSizeProc(thandle_t fd
)
170 std::ostream
*os
= reinterpret_cast<std::ostream
*>(fd
);
171 std::ios::pos_type pos
= os
->tellp();
172 os
->seekp(0, std::ios::end
);
173 std::ios::pos_type size
= os
->tellp();
174 os
->seekp(pos
, std::ios::beg
);
178 static int mapFileProc(thandle_t fd
, tdata_t
*buf
, toff_t
*size
)
183 static void unmapFileProc(thandle_t fd
, tdata_t buf
, toff_t size
)
187 static void warningHandler(const char *module
, const char *fmt
, va_list ap
)
191 #ifdef OSG_HAS_VSNPRINTF
192 vsnprintf(buffer
, sizeof(buffer
) - 1, fmt
, ap
);
194 vsprintf(buffer
, fmt
, ap
);
197 FWARNING(("TiffLib: %s;%s\n", module
? module
: "Mod", buffer
));
200 static void errorHandler(const char *module
, const char *fmt
, va_list ap
)
204 #ifdef OSG_HAS_VSNPRINTF
205 vsnprintf(buffer
, sizeof(buffer
) - 1, fmt
, ap
);
207 vsprintf(buffer
, fmt
, ap
);
210 FFATAL(("TiffLib: %s;%s\n", module
? module
: "Mod", buffer
));
212 #endif // OSG_WITH_TIF
215 TIFImageFileType
TIFImageFileType:: _the("image/tiff",
218 (OSG_READ_SUPPORTED
|
219 OSG_WRITE_SUPPORTED
));
222 //-------------------------------------------------------------------------
223 /*! Tries to fill the image object with the data read from
224 the given fileName. Returns true on success.
227 bool TIFImageFileType::read( Image
*OSG_TIF_ARG(pImage
),
228 std::istream
&OSG_TIF_ARG(is
),
229 const std::string
&OSG_TIF_ARG(mimetype
))
233 TIFF
*in
= TIFFClientOpen("dummy", "rm", thandle_t(&is
),
245 TIFFGetField(in
, TIFFTAG_IMAGEWIDTH
, &w
);
246 TIFFGetField(in
, TIFFTAG_IMAGELENGTH
, &h
);
250 TIFFGetField(in
, TIFFTAG_XRESOLUTION
, &res_x
);
251 TIFFGetField(in
, TIFFTAG_YRESOLUTION
, &res_y
);
252 TIFFGetField(in
, TIFFTAG_RESOLUTIONUNIT
, &res_unit
);
253 if (res_unit
== RESUNIT_CENTIMETER
)
255 // convert it to dpi.
258 res_unit
= Image::OSG_RESUNIT_INCH
;
262 TIFFGetFieldDefaulted(in
, TIFFTAG_SAMPLESPERPIXEL
, &bpp
);
264 { // accept unspecified extra samples as associated alpha
267 TIFFGetFieldDefaulted(in
,
268 TIFFTAG_EXTRASAMPLES
,
271 if (sampleinfo
&& sampleinfo
[0] == EXTRASAMPLE_UNSPECIFIED
)
273 uint16 si
= EXTRASAMPLE_ASSOCALPHA
;
274 TIFFSetField(in
, TIFFTAG_EXTRASAMPLES
, 1, &si
);
277 Image::PixelFormat type
= Image::OSG_INVALID_PF
;
281 type
= Image::OSG_L_PF
;
284 type
= Image::OSG_LA_PF
;
287 type
= Image::OSG_RGB_PF
;
290 type
= Image::OSG_RGBA_PF
;
294 char errorMessage
[1024];
295 if (TIFFRGBAImageOK(in
, errorMessage
) == 0)
297 SWARNING
<< "Tiff reader failed: " << errorMessage
<< std::endl
;
302 UInt32 numPixels
= w
* h
;
303 uint32
*buffer
= new uint32
[numPixels
];
304 if (TIFFReadRGBAImage(in
, w
, h
, buffer
, 1) == 0)
313 pImage
->set(type
, w
, h
);
314 pImage
->setResX(res_x
);
315 pImage
->setResY(res_y
);
316 pImage
->setResUnit(res_unit
);
318 UChar8
*dst
= pImage
->editData();
319 uint32
*src
= buffer
;
323 for (UInt32 i
= numPixels
; i
> 0; --i
)
325 *dst
++ = TIFFGetR(*src
);
326 *dst
++ = TIFFGetG(*src
);
327 *dst
++ = TIFFGetB(*src
);
328 *dst
++ = TIFFGetA(*src
++);
332 for (UInt32 i
= numPixels
; i
> 0; --i
)
334 *dst
++ = TIFFGetR(*src
);
335 *dst
++ = TIFFGetG(*src
);
336 *dst
++ = TIFFGetB(*src
++);
340 for (UInt32 i
= numPixels
; i
> 0; --i
)
342 *dst
++ = TIFFGetG(*src
);
343 *dst
++ = TIFFGetA(*src
++);
347 for (UInt32 i
= numPixels
; i
> 0; --i
)
348 *dst
++ = TIFFGetG(*src
++);
358 SWARNING
<< getMimeType()
359 << " read is not compiled into the current binary "
363 #endif // OSG_WITH_TIF
366 //-------------------------------------------------------------------------
367 /*! Tries to write the image object to the given output stream.
368 Returns true on success.
371 bool TIFImageFileType::write(const Image
*OSG_TIF_ARG(pImage
),
372 std::ostream
&OSG_TIF_ARG(os
),
373 const std::string
&OSG_TIF_ARG(mimetype
))
375 bool retCode
= false;
378 if(pImage
->getDimension() < 1 || pImage
->getDimension() > 2)
380 FWARNING(("TIFImageFileType::write: invalid dimension %d!\n",
381 pImage
->getDimension()));
386 TIFF
*out
= TIFFClientOpen("dummy", "wm", thandle_t(&os
),
395 int lineSize
= pImage
->getWidth() * pImage
->getBpp();
397 int samplesPerPixel
= 0;
401 // TODO: implement all cases correct
402 switch(pImage
->getBpp())
406 photometric
= PHOTOMETRIC_MINISBLACK
;
410 photometric
= PHOTOMETRIC_MINISBLACK
;
414 photometric
= PHOTOMETRIC_RGB
;
418 photometric
= PHOTOMETRIC_RGB
;
420 case 12: // RGB 32bit float
422 photometric
= PHOTOMETRIC_RGB
;
424 case 16: // RGBA 32bit float
426 photometric
= PHOTOMETRIC_RGB
;
431 int fmt
= SAMPLEFORMAT_UINT
;
432 switch(pImage
->getDataType())
434 case Image::OSG_UINT8_IMAGEDATA
:
436 fmt
= SAMPLEFORMAT_UINT
;
438 case Image::OSG_FLOAT32_IMAGEDATA
:
440 fmt
= SAMPLEFORMAT_IEEEFP
;
443 FWARNING(("TIFImageFileType::write: image data type not "
451 TIFFSetField(out
, TIFFTAG_IMAGEWIDTH
, pImage
->getWidth());
452 TIFFSetField(out
, TIFFTAG_IMAGELENGTH
, pImage
->getHeight());
453 TIFFSetField(out
, TIFFTAG_XRESOLUTION
, pImage
->getResX());
454 TIFFSetField(out
, TIFFTAG_YRESOLUTION
, pImage
->getResY());
455 TIFFSetField(out
, TIFFTAG_RESOLUTIONUNIT
, pImage
->getResUnit());
456 TIFFSetField(out
, TIFFTAG_ORIENTATION
, ORIENTATION_TOPLEFT
);
457 TIFFSetField(out
, TIFFTAG_SAMPLESPERPIXEL
, samplesPerPixel
);
458 TIFFSetField(out
, TIFFTAG_BITSPERSAMPLE
, bps
);
459 TIFFSetField(out
, TIFFTAG_SAMPLEFORMAT
, fmt
);
460 TIFFSetField(out
, TIFFTAG_PLANARCONFIG
, PLANARCONFIG_CONTIG
);
461 TIFFSetField(out
, TIFFTAG_PHOTOMETRIC
, photometric
);
463 std::string compressionType
;
464 if(getOption("compressionType", compressionType
) &&
465 compressionType
== "LZW" )
467 TIFFSetField(out
, TIFFTAG_COMPRESSION
, COMPRESSION_LZW
);
471 TIFFSetField(out
, TIFFTAG_COMPRESSION
, COMPRESSION_NONE
);
474 TIFFSetField(out
, TIFFTAG_ROWSPERSTRIP
, TIFFDefaultStripSize(out
, 0));
476 for(row
= 0; row
< pImage
->getHeight(); row
++)
480 ((pImage
->getHeight() - row
- 1) * lineSize
);
482 if(TIFFWriteScanline(out
,
483 tdata_t(const_cast<UChar8
*>(data
)),
497 SWARNING
<< getMimeType()
498 << " write is not compiled into the current binary "
505 bool TIFImageFileType::validateHeader(const Char8
*fileName
, bool &implemented
)
512 FILE *file
= fopen(fileName
, "rb");
519 fread(static_cast<void *>(&magic
[0]), 2, 1, file
);
522 if(magic
== "MM" || magic
== "II")
530 //-------------------------------------------------------------------------
532 Tries to determine the mime type of the data provided by an input stream
533 by searching for magic bytes. Returns the mime type or an empty string
534 when the function could not determine the mime type.
537 std::string
TIFImageFileType::determineMimetypeFromStream(std::istream
&is
)
541 is
.read(filecode
, 4);
542 is
.seekg(-4, std::ios::cur
);
544 if(strncmp(filecode
, "MM\x00\x2a", 4) == 0)
545 return std::string(getMimeType());
547 if(strncmp(filecode
, "II\x2a\x00", 4) == 0)
548 return std::string(getMimeType());
550 return std::string();
553 //-------------------------------------------------------------------------
554 /*! Constructor used for the singleton object
557 TIFImageFileType::TIFImageFileType(const Char8
*mimeType
,
558 const Char8
*suffixArray
[],
559 UInt16 suffixByteCount
,
566 static bool initTIFFLib
= true;
573 TIFFSetWarningHandler(&warningHandler
);
574 TIFFSetErrorHandler (&errorHandler
);
579 //-------------------------------------------------------------------------
583 TIFImageFileType::~TIFImageFileType(void)