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 //-------------------------------
41 #if __GNUC__ >= 4 || __GNUC_MINOR__ >=3
42 #pragma GCC diagnostic warning "-Wold-style-cast"
48 #include "OSGConfig.h"
50 #include "OSGGDALImageFileType.h"
51 #include "OSGGeoReferenceAttachment.h"
54 #include "gdal_priv.h"
55 #include "ogr_srs_api.h"
56 #include "cpl_multiproc.h"
62 # define OSG_GDAL_ARG(ARG) ARG
64 # define OSG_GDAL_ARG(ARG)
67 # define OSG_GDAL_ARG(ARG) ARG
70 // Static Class Varible implementations:
71 static const OSG::Char8
*suffixArray
[] =
73 "gtif", "gtiff", "hdf4", "adf"
78 GDALBlockAccessor::~GDALBlockAccessor(void)
85 bool GDALBlockAccessor::isOpen(void)
88 return (_pDataset
!= NULL
);
95 GDALBlockAccessor::GDALBlockAccessor(void) :
105 void GDALBlockAccessor::open(const Char8
*szFilename
)
108 _pDataset
= static_cast<GDALDataset
*>(GDALOpen(szFilename
, GA_ReadOnly
));
110 if(_pDataset
!= NULL
)
112 _pGeoRef
= GeoReferenceAttachment::create();
114 double adfGeoTransform
[6];
116 if(_pDataset
->GetGeoTransform(adfGeoTransform
) == CE_None
)
118 _pGeoRef
->editOrigin().setValues(adfGeoTransform
[0],
121 _pGeoRef
->editPixelSize().setValues(adfGeoTransform
[1],
124 if(GDALGetProjectionRef(_pDataset
) != NULL
)
126 OGRSpatialReferenceH hSRS
;
128 Char8
*szProjection
=
129 const_cast<char *>(GDALGetProjectionRef(_pDataset
));
131 hSRS
= OSRNewSpatialReference(NULL
);
133 if(OSRImportFromWkt(hSRS
, &szProjection
) == CE_None
)
135 _pGeoRef
->editEllipsoidAxis().setValues(
136 OSRGetSemiMajor(hSRS
, NULL
),
137 OSRGetSemiMinor(hSRS
, NULL
));
139 const Char8
*szDatum
= OSRGetAttrValue(hSRS
, "DATUM", 0);
141 if(szDatum
!= NULL
&& 0 == strcmp(szDatum
, "WGS_1984"))
143 _pGeoRef
->editDatum() =
144 GeoReferenceAttachment::WGS84
;
148 fprintf(stderr
, "Unknow datum %s\n",
151 _pGeoRef
->editDatum() =
152 GeoReferenceAttachment::UnknownDatum
;
156 OSRDestroySpatialReference(hSRS
);
160 int nBlockXSize
, nBlockYSize
;
161 int bGotMin
, bGotMax
;
164 _pBand
= _pDataset
->GetRasterBand(1);
166 _pBand
->GetBlockSize(&nBlockXSize
, &nBlockYSize
);
168 adfMinMax
[0] = _pBand
->GetMinimum(&bGotMin
);
169 adfMinMax
[1] = _pBand
->GetMaximum(&bGotMax
);
171 if(!(bGotMin
&& bGotMax
))
173 GDALComputeRasterMinMax(GDALRasterBandH(_pBand
), TRUE
, adfMinMax
);
178 _eImgFormat
= Image::OSG_INVALID_PF
;
180 switch(_pDataset
->GetRasterCount())
183 _eImgFormat
= Image::OSG_L_PF
;
186 _eImgFormat
= Image::OSG_LA_PF
;
189 _eImgFormat
= Image::OSG_RGB_PF
;
192 _eImgFormat
= Image::OSG_RGBA_PF
;
196 _eImgType
= Image::OSG_INVALID_IMAGEDATATYPE
;
198 switch(_pBand
->GetRasterDataType())
201 _eImgType
= Image::OSG_UINT8_IMAGEDATA
;
205 _eImgType
= Image::OSG_UINT16_IMAGEDATA
;
209 _eImgType
= Image::OSG_INT16_IMAGEDATA
;
213 _eImgType
= Image::OSG_UINT32_IMAGEDATA
;
217 _eImgType
= Image::OSG_INT32_IMAGEDATA
;
221 _eImgType
= Image::OSG_FLOAT32_IMAGEDATA
;
230 GDALClose(_pDataset
);
236 _vSize
[0] = _pDataset
->GetRasterXSize();
237 _vSize
[1] = _pDataset
->GetRasterYSize();
239 _fNoDataValue
= _pBand
->GetNoDataValue();
241 _pGeoRef
->setNoDataValue(_fNoDataValue
);
247 bool GDALBlockAccessor::readBlockA16(Vec2i vSampleOrigin
,
250 Int32 iTargetSizeBytes
)
257 UInt8
*pDst
= reinterpret_cast<UInt8
*>(pTarget
);
259 Int32 xMin
= vSampleOrigin
.x();
260 Int32 xMax
= vSampleOrigin
.x() + iTextureSize
;
262 Int32 yMin
= vSampleOrigin
.y();
263 Int32 yMax
= vSampleOrigin
.y() + iTextureSize
;
265 for(Int32 y
= yMin
; y
< yMax
; y
++)
267 for(Int32 x
= xMin
; x
< xMax
; x
++)
269 for(UInt32 i
= 0; i
< 2; i
++)
277 destIdx
+= (iTextureSize
- (xMax
- xMin
)) * 2;
284 bool GDALBlockAccessor::readBlockA16(Vec2i vSampleOrigin
,
287 Int32 iTargetSizeBytes
)
290 Int32 xMin
= vSampleOrigin
.x();
291 Int32 xMax
= vSampleOrigin
.x() + iTextureSize
;
293 Int32 yMin
= vSampleOrigin
.y();
294 Int32 yMax
= vSampleOrigin
.y() + iTextureSize
;
296 if(xMax
> _vSize
[0] || yMax
> _vSize
[1])
301 _vI16Buffer
.resize(iTextureSize
* iTextureSize
);
303 Int32 iSampleX
= osgMin(_vSize
[0] - vSampleOrigin
.x(), iTextureSize
);
304 Int32 iSampleY
= osgMin(_vSize
[1] - vSampleOrigin
.y(), iTextureSize
);
306 CPLErr res
= _pBand
->RasterIO(GF_Read
,
318 if(res
== CE_Failure
|| res
== CE_Fatal
)
321 for(Int32 y
= yMin
; y
< yMax
; y
++)
323 for(Int32 x
= xMin
; x
< xMax
; x
++)
325 if(x
>= _vSize
[0] || y
>= _vSize
[1])
327 pTarget
[destIdx
] = Int16(_fNoDataValue
);
331 pTarget
[destIdx
] = _vI16Buffer
[srcIdx
];
342 CPLErr res
= _pBand
->RasterIO(GF_Read
,
354 if(res
== CE_Failure
|| res
== CE_Fatal
)
363 /*! \class GDALImageFileType
365 Image File Type to read/write and store/restore Image objects as
366 GDAL (tif/tiff suffix) data.
368 To be able to load TIFF images you need the IJG TIFF library,
369 (check the Prerequisites page on www.opensg.org).
370 The lib comes with all Linux distributions.
372 You have to --enable-tif in the configure line to enable
373 the singleton object.
377 GDALImageFileType
GDALImageFileType:: _the("image/gdal",
380 (OSG_READ_SUPPORTED
));
383 //-------------------------------------------------------------------------
384 /*! Tries to fill the image object with the data read from
385 the given fileName. Returns true on success.
388 bool GDALImageFileType::read( Image
*OSG_GDAL_ARG(pImage
),
389 const Char8
*OSG_GDAL_ARG(fileName
))
392 bool returnValue
= false;
394 GDALDataset
*pDataset
;
396 pDataset
= static_cast<GDALDataset
*>(GDALOpen(fileName
, GA_ReadOnly
));
400 GeoReferenceAttachmentUnrecPtr pGeoRef
=
401 GeoReferenceAttachment::create();
403 pImage
->addAttachment(pGeoRef
);
405 double adfGeoTransform
[6];
407 if(pDataset
->GetGeoTransform(adfGeoTransform
) == CE_None
)
409 pGeoRef
->editOrigin().setValues(adfGeoTransform
[0],
412 pGeoRef
->editPixelSize().setValues(adfGeoTransform
[1],
415 if(GDALGetProjectionRef(pDataset
) != NULL
)
417 OGRSpatialReferenceH hSRS
;
419 Char8
*szProjection
=
420 const_cast<char *>(GDALGetProjectionRef(pDataset
));
422 hSRS
= OSRNewSpatialReference(NULL
);
424 if(OSRImportFromWkt(hSRS
, &szProjection
) == CE_None
)
426 pGeoRef
->editEllipsoidAxis().setValues(
427 OSRGetSemiMajor(hSRS
, NULL
),
428 OSRGetSemiMinor(hSRS
, NULL
));
430 const Char8
*szDatum
= OSRGetAttrValue(hSRS
, "DATUM", 0);
432 if(szDatum
!= NULL
&& 0 == strcmp(szDatum
, "WGS_1984"))
434 pGeoRef
->editDatum() =
435 GeoReferenceAttachment::WGS84
;
439 fprintf(stderr
, "Unknow datum %s\n",
442 pGeoRef
->editDatum() =
443 GeoReferenceAttachment::UnknownDatum
;
447 OSRDestroySpatialReference(hSRS
);
451 GDALRasterBand
*pBand
;
452 int nBlockXSize
, nBlockYSize
;
453 int bGotMin
, bGotMax
;
456 pBand
= pDataset
->GetRasterBand( 1 );
457 pBand
->GetBlockSize( &nBlockXSize
, &nBlockYSize
);
459 adfMinMax
[0] = pBand
->GetMinimum( &bGotMin
);
460 adfMinMax
[1] = pBand
->GetMaximum( &bGotMax
);
462 if(!(bGotMin
&& bGotMax
))
463 GDALComputeRasterMinMax(GDALRasterBandH(pBand
), TRUE
, adfMinMax
);
465 pBand
= pDataset
->GetRasterBand(1);
469 Image::PixelFormat ePF
= Image::OSG_INVALID_PF
;
471 switch(pDataset
->GetRasterCount())
474 ePF
= Image::OSG_L_PF
;
477 ePF
= Image::OSG_LA_PF
;
480 ePF
= Image::OSG_RGB_PF
;
483 ePF
= Image::OSG_RGBA_PF
;
487 Image::Type eDT
= Image::OSG_INVALID_IMAGEDATATYPE
;
489 switch(pBand
->GetRasterDataType())
492 eDT
= Image::OSG_UINT8_IMAGEDATA
;
496 eDT
= Image::OSG_UINT16_IMAGEDATA
;
500 eDT
= Image::OSG_INT16_IMAGEDATA
;
504 eDT
= Image::OSG_UINT32_IMAGEDATA
;
508 eDT
= Image::OSG_INT32_IMAGEDATA
;
512 eDT
= Image::OSG_FLOAT32_IMAGEDATA
;
528 pDataset
->GetRasterXSize(),
529 pDataset
->GetRasterYSize(),
537 UChar8
*dst
= pImage
->editData();
539 CPLErr res
= pBand
->RasterIO(GF_Read
,
542 pDataset
->GetRasterXSize(),
543 pDataset
->GetRasterYSize(),
545 pDataset
->GetRasterXSize(),
546 pDataset
->GetRasterYSize(),
547 pBand
->GetRasterDataType(),
551 if(res
== CE_Failure
|| res
== CE_Fatal
)
554 pGeoRef
->setNoDataValue(pBand
->GetNoDataValue());
566 SWARNING
<< getMimeType()
567 << " read is not compiled into the current binary "
571 #endif // OSG_WITH_GDAL
574 //-------------------------------------------------------------------------
575 /*! Tries to write the image object to the given output stream.
576 Returns true on success.
579 bool GDALImageFileType::write(const Image
*OSG_GDAL_ARG(pImage
),
580 const Char8
*OSG_GDAL_ARG(fileName
))
582 bool retCode
= false;
584 #ifdef OSG_WITH_GDALX
585 if(pImage
->getDimension() < 1 || pImage
->getDimension() > 2)
587 FWARNING(("TIFImageFileType::write: invalid dimension %d!\n",
588 pImage
->getDimension()));
593 TIFF
*out
= TIFFClientOpen("dummy", "wm", (thandle_t
)&os
,
602 int lineSize
= pImage
->getWidth() * pImage
->getBpp();
604 int samplesPerPixel
= 0;
608 // TODO: implement all cases correct
609 switch(pImage
->getBpp())
613 photometric
= PHOTOMETRIC_MINISBLACK
;
617 photometric
= PHOTOMETRIC_MINISBLACK
;
621 photometric
= PHOTOMETRIC_RGB
;
625 photometric
= PHOTOMETRIC_RGB
;
631 TIFFSetField(out
, TIFFTAG_IMAGEWIDTH
, pImage
->getWidth());
632 TIFFSetField(out
, TIFFTAG_IMAGELENGTH
, pImage
->getHeight());
633 TIFFSetField(out
, TIFFTAG_XRESOLUTION
, pImage
->getResX());
634 TIFFSetField(out
, TIFFTAG_YRESOLUTION
, pImage
->getResY());
635 TIFFSetField(out
, TIFFTAG_RESOLUTIONUNIT
, pImage
->getResUnit());
636 TIFFSetField(out
, TIFFTAG_ORIENTATION
, ORIENTATION_TOPLEFT
);
637 TIFFSetField(out
, TIFFTAG_SAMPLESPERPIXEL
, samplesPerPixel
);
638 TIFFSetField(out
, TIFFTAG_BITSPERSAMPLE
, 8);
639 TIFFSetField(out
, TIFFTAG_PLANARCONFIG
, PLANARCONFIG_CONTIG
);
640 TIFFSetField(out
, TIFFTAG_PHOTOMETRIC
, photometric
);
642 if(_options
.find("compressionType=LZW") != std::string::npos
)
644 TIFFSetField(out
, TIFFTAG_COMPRESSION
, COMPRESSION_LZW
);
648 TIFFSetField(out
, TIFFTAG_COMPRESSION
, COMPRESSION_NONE
);
651 TIFFSetField(out
, TIFFTAG_ROWSPERSTRIP
, TIFFDefaultStripSize(out
, 0));
653 for(row
= 0; row
< pImage
->getHeight(); row
++)
657 ((pImage
->getHeight() - row
- 1) * lineSize
);
659 if(TIFFWriteScanline(out
,
660 (tdata_t
) const_cast<UChar8
*>(data
),
674 SWARNING
<< getMimeType()
675 << " write is not compiled into the current binary "
682 bool GDALImageFileType::validateHeader(const Char8
*fileName
, bool &implemented
)
690 ImageBlockAccessorPtr
GDALImageFileType::open(const Char8
*fileName
)
692 GDALBlockAccessorPtr
returnValue(new GDALBlockAccessor
);
694 returnValue
->open(fileName
);
700 //-------------------------------------------------------------------------
701 /*! Constructor used for the singleton object
704 GDALImageFileType::GDALImageFileType(const Char8
*mimeType
,
705 const Char8
*suffixArray
[],
706 UInt16 suffixByteCount
,
713 // static bool initTIFFLib = true;
720 //-------------------------------------------------------------------------
724 GDALImageFileType::~GDALImageFileType(void)
727 GDALDestroyDriverManager();