fixed: auto_ptr -> unique_ptr
[opensg.git] / Source / System / Image / FileIO / OSGGDALImageFileType.cpp
blob3992a87b58bfcb9d11796256ce445c7ea6485ac7
1 /*---------------------------------------------------------------------------*\
2 * OpenSG *
3 * *
4 * *
5 * Copyright (C) 2000-2002 by the OpenSG Forum *
6 * *
7 * www.opensg.org *
8 * *
9 * contact: dirk@opensg.org, gerrit.voss@vossg.org, jbehr@zgdv.de *
10 * *
11 \*---------------------------------------------------------------------------*/
12 /*---------------------------------------------------------------------------*\
13 * License *
14 * *
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. *
18 * *
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. *
23 * *
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. *
27 * *
28 \*---------------------------------------------------------------------------*/
29 /*---------------------------------------------------------------------------*\
30 * Changes *
31 * *
32 * *
33 * *
34 * *
35 * *
36 * *
37 \*---------------------------------------------------------------------------*/
38 //-------------------------------
39 // Includes
40 //-------------------------------
41 #if __GNUC__ >= 4 || __GNUC_MINOR__ >=3
42 #pragma GCC diagnostic warning "-Wold-style-cast"
43 #endif
45 #include <cstdlib>
46 #include <cstdio>
48 #include "OSGConfig.h"
50 #include "OSGGDALImageFileType.h"
51 #include "OSGGeoReferenceAttachment.h"
53 #ifdef OSG_WITH_GDAL
54 #include "gdal_priv.h"
55 #include "ogr_srs_api.h"
56 #include "cpl_multiproc.h"
57 #endif
60 #ifndef OSG_DO_DOC
61 # ifdef OSG_WITH_GDAL
62 # define OSG_GDAL_ARG(ARG) ARG
63 # else
64 # define OSG_GDAL_ARG(ARG)
65 # endif
66 #else
67 # define OSG_GDAL_ARG(ARG) ARG
68 #endif
70 // Static Class Varible implementations:
71 static const OSG::Char8 *suffixArray[] =
73 "gtif", "gtiff", "hdf4", "adf"
76 OSG_BEGIN_NAMESPACE
78 GDALBlockAccessor::~GDALBlockAccessor(void)
80 #ifdef OSG_WITH_GDAL
81 GDALClose(_pDataset);
82 #endif
85 bool GDALBlockAccessor::isOpen(void)
87 #ifdef OSG_WITH_GDAL
88 return (_pDataset != NULL);
89 #else
90 return false;
91 #endif
95 GDALBlockAccessor::GDALBlockAccessor(void) :
96 Inherited ( ),
97 #ifdef OSG_WITH_GDAL
98 _pDataset (NULL),
99 _pBand (NULL),
100 #endif
101 _vI16Buffer( )
105 void GDALBlockAccessor::open(const Char8 *szFilename)
107 #ifdef OSG_WITH_GDAL
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],
119 adfGeoTransform[3]);
121 _pGeoRef->editPixelSize().setValues(adfGeoTransform[1],
122 adfGeoTransform[5]);
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;
146 else
148 fprintf(stderr, "Unknow datum %s\n",
149 szDatum);
151 _pGeoRef->editDatum() =
152 GeoReferenceAttachment::UnknownDatum;
156 OSRDestroySpatialReference(hSRS);
160 int nBlockXSize, nBlockYSize;
161 int bGotMin, bGotMax;
162 double adfMinMax[2];
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);
176 if(_pBand != NULL)
178 _eImgFormat = Image::OSG_INVALID_PF;
180 switch(_pDataset->GetRasterCount())
182 case 1:
183 _eImgFormat = Image::OSG_L_PF;
184 break;
185 case 2:
186 _eImgFormat = Image::OSG_LA_PF;
187 break;
188 case 3:
189 _eImgFormat = Image::OSG_RGB_PF;
190 break;
191 case 4:
192 _eImgFormat = Image::OSG_RGBA_PF;
193 break;
196 _eImgType = Image::OSG_INVALID_IMAGEDATATYPE;
198 switch(_pBand->GetRasterDataType())
200 case GDT_Byte:
201 _eImgType = Image::OSG_UINT8_IMAGEDATA;
202 break;
204 case GDT_UInt16:
205 _eImgType = Image::OSG_UINT16_IMAGEDATA;
206 break;
208 case GDT_Int16:
209 _eImgType = Image::OSG_INT16_IMAGEDATA;
210 break;
212 case GDT_UInt32:
213 _eImgType = Image::OSG_UINT32_IMAGEDATA;
214 break;
216 case GDT_Int32:
217 _eImgType = Image::OSG_INT32_IMAGEDATA;
218 break;
220 case GDT_Float32:
221 _eImgType = Image::OSG_FLOAT32_IMAGEDATA;
222 break;
224 case GDT_Float64:
225 case GDT_CInt16:
226 case GDT_CInt32:
227 case GDT_CFloat32:
228 case GDT_CFloat64:
229 default:
230 GDALClose(_pDataset);
231 _pDataset = NULL;
232 break;
236 _vSize[0] = _pDataset->GetRasterXSize();
237 _vSize[1] = _pDataset->GetRasterYSize();
239 _fNoDataValue = _pBand->GetNoDataValue();
241 _pGeoRef->setNoDataValue(_fNoDataValue);
244 #endif
247 bool GDALBlockAccessor::readBlockA16(Vec2i vSampleOrigin,
248 Int32 iTextureSize,
249 UInt16 *pTarget,
250 Int32 iTargetSizeBytes)
252 #ifdef OSG_WITH_GDAL
253 OSG_ASSERT(false);
255 UInt32 destIdx = 0;
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++)
271 pDst[destIdx] = 0;
273 destIdx++;
277 destIdx += (iTextureSize - (xMax - xMin)) * 2;
279 #endif
281 return false;
284 bool GDALBlockAccessor::readBlockA16(Vec2i vSampleOrigin,
285 Int32 iTextureSize,
286 Int16 *pTarget,
287 Int32 iTargetSizeBytes)
289 #ifdef OSG_WITH_GDAL
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])
298 UInt32 destIdx = 0;
299 UInt32 srcIdx = 0;
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,
307 vSampleOrigin.x(),
308 vSampleOrigin.y(),
309 iSampleX,
310 iSampleY,
311 &(_vI16Buffer[0]),
312 iSampleX,
313 iSampleY,
314 GDT_Int16,
316 0 );
318 if(res == CE_Failure || res == CE_Fatal)
319 return false;
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);
329 else
331 pTarget[destIdx] = _vI16Buffer[srcIdx];
333 srcIdx++;
336 destIdx++;
340 else
342 CPLErr res = _pBand->RasterIO(GF_Read,
343 vSampleOrigin.x(),
344 vSampleOrigin.y(),
345 iTextureSize,
346 iTextureSize,
347 pTarget,
348 iTextureSize,
349 iTextureSize,
350 GDT_Int16,
352 0 );
354 if(res == CE_Failure || res == CE_Fatal)
355 return false;
357 #endif
359 return true;
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",
378 suffixArray,
379 sizeof(suffixArray),
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))
391 #ifdef OSG_WITH_GDAL
392 bool returnValue = false;
394 GDALDataset *pDataset;
396 pDataset = static_cast<GDALDataset *>(GDALOpen(fileName, GA_ReadOnly));
398 if(pDataset != NULL)
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],
410 adfGeoTransform[3]);
412 pGeoRef->editPixelSize().setValues(adfGeoTransform[1],
413 adfGeoTransform[5]);
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;
437 else
439 fprintf(stderr, "Unknow datum %s\n",
440 szDatum);
442 pGeoRef->editDatum() =
443 GeoReferenceAttachment::UnknownDatum;
447 OSRDestroySpatialReference(hSRS);
451 GDALRasterBand *pBand;
452 int nBlockXSize, nBlockYSize;
453 int bGotMin, bGotMax;
454 double adfMinMax[2];
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);
467 if(pBand != NULL)
469 Image::PixelFormat ePF = Image::OSG_INVALID_PF;
471 switch(pDataset->GetRasterCount())
473 case 1:
474 ePF = Image::OSG_L_PF;
475 break;
476 case 2:
477 ePF = Image::OSG_LA_PF;
478 break;
479 case 3:
480 ePF = Image::OSG_RGB_PF;
481 break;
482 case 4:
483 ePF = Image::OSG_RGBA_PF;
484 break;
487 Image::Type eDT = Image::OSG_INVALID_IMAGEDATATYPE;
489 switch(pBand->GetRasterDataType())
491 case GDT_Byte:
492 eDT = Image::OSG_UINT8_IMAGEDATA;
493 break;
495 case GDT_UInt16:
496 eDT = Image::OSG_UINT16_IMAGEDATA;
497 break;
499 case GDT_Int16:
500 eDT = Image::OSG_INT16_IMAGEDATA;
501 break;
503 case GDT_UInt32:
504 eDT = Image::OSG_UINT32_IMAGEDATA;
505 break;
507 case GDT_Int32:
508 eDT = Image::OSG_INT32_IMAGEDATA;
509 break;
511 case GDT_Float32:
512 eDT = Image::OSG_FLOAT32_IMAGEDATA;
513 break;
515 case GDT_Float64:
516 case GDT_CInt16:
517 case GDT_CInt32:
518 case GDT_CFloat32:
519 case GDT_CFloat64:
520 default:
521 GDALClose(pDataset);
522 return returnValue;
523 break;
527 pImage->set(ePF,
528 pDataset->GetRasterXSize(),
529 pDataset->GetRasterYSize(),
533 0.0,
534 NULL,
535 eDT);
537 UChar8 *dst = pImage->editData();
539 CPLErr res = pBand->RasterIO(GF_Read,
542 pDataset->GetRasterXSize(),
543 pDataset->GetRasterYSize(),
544 dst,
545 pDataset->GetRasterXSize(),
546 pDataset->GetRasterYSize(),
547 pBand->GetRasterDataType(),
549 0 );
551 if(res == CE_Failure || res == CE_Fatal)
552 return returnValue;
554 pGeoRef->setNoDataValue(pBand->GetNoDataValue());
556 returnValue = true;
559 GDALClose(pDataset);
562 return returnValue;
564 #else
566 SWARNING << getMimeType()
567 << " read is not compiled into the current binary "
568 << std::endl;
569 return false;
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()));
590 return false;
593 TIFF *out = TIFFClientOpen("dummy", "wm", (thandle_t)&os,
594 osReadProc,
595 osWriteProc,
596 osSeekProc,
597 closeProc,
598 osSizeProc,
599 mapFileProc,
600 unmapFileProc);
602 int lineSize = pImage->getWidth() * pImage->getBpp();
603 int photometric = 0;
604 int samplesPerPixel = 0;
605 const UChar8 *data;
606 int row;
608 // TODO: implement all cases correct
609 switch(pImage->getBpp())
611 case 1:
612 samplesPerPixel = 1;
613 photometric = PHOTOMETRIC_MINISBLACK;
614 break;
615 case 2:
616 samplesPerPixel = 2;
617 photometric = PHOTOMETRIC_MINISBLACK;
618 break;
619 case 3:
620 samplesPerPixel = 3;
621 photometric = PHOTOMETRIC_RGB;
622 break;
623 case 4:
624 samplesPerPixel = 4;
625 photometric = PHOTOMETRIC_RGB;
626 break;
629 if(out)
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);
646 else
648 TIFFSetField(out, TIFFTAG_COMPRESSION, COMPRESSION_NONE);
651 TIFFSetField(out, TIFFTAG_ROWSPERSTRIP, TIFFDefaultStripSize(out, 0));
653 for(row = 0; row < pImage->getHeight(); row++)
655 data =
656 pImage->getData() +
657 ((pImage->getHeight() - row - 1) * lineSize);
659 if(TIFFWriteScanline(out,
660 (tdata_t) const_cast<UChar8 *>(data),
661 row,
662 0) < 0)
664 break;
668 TIFFClose(out);
670 retCode = true;
673 #else
674 SWARNING << getMimeType()
675 << " write is not compiled into the current binary "
676 << std::endl;
677 #endif
679 return retCode;
682 bool GDALImageFileType::validateHeader(const Char8 *fileName, bool &implemented)
684 implemented = true;
686 return true;
689 #if 1
690 ImageBlockAccessorPtr GDALImageFileType::open(const Char8 *fileName)
692 GDALBlockAccessorPtr returnValue(new GDALBlockAccessor);
694 returnValue->open(fileName);
696 return returnValue;
698 #endif
700 //-------------------------------------------------------------------------
701 /*! Constructor used for the singleton object
704 GDALImageFileType::GDALImageFileType(const Char8 *mimeType,
705 const Char8 *suffixArray[],
706 UInt16 suffixByteCount,
707 UInt32 flags) :
708 Inherited(mimeType,
709 suffixArray,
710 suffixByteCount,
711 flags )
713 // static bool initTIFFLib = true;
715 #ifdef OSG_WITH_GDAL
716 GDALAllRegister();
717 #endif
720 //-------------------------------------------------------------------------
721 /*! Destructor
724 GDALImageFileType::~GDALImageFileType(void)
726 #ifdef OSG_WITH_GDAL
727 GDALDestroyDriverManager();
728 CPLCleanupTLS();
729 #endif
732 OSG_END_NAMESPACE