LCOV - code coverage report
Current view: directory - frmts/fit - fitdataset.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 525 290 55.2 %
Date: 2011-12-18 Functions: 24 16 66.7 %

       1                 : /******************************************************************************
       2                 :  * $Id: fitdataset.cpp 23060 2011-09-05 17:58:30Z rouault $
       3                 :  *
       4                 :  * Project:  FIT Driver
       5                 :  * Purpose:  Implement FIT Support - not using the SGI iflFIT library.
       6                 :  * Author:   Philip Nemec, nemec@keyholecorp.com
       7                 :  *
       8                 :  ******************************************************************************
       9                 :  * Copyright (c) 2001, Keyhole, Inc.
      10                 :  *
      11                 :  * Permission is hereby granted, free of charge, to any person obtaining a
      12                 :  * copy of this software and associated documentation files (the "Software"),
      13                 :  * to deal in the Software without restriction, including without limitation
      14                 :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      15                 :  * and/or sell copies of the Software, and to permit persons to whom the
      16                 :  * Software is furnished to do so, subject to the following conditions:
      17                 :  *
      18                 :  * The above copyright notice and this permission notice shall be included
      19                 :  * in all copies or substantial portions of the Software.
      20                 :  *
      21                 :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      22                 :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      23                 :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      24                 :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      25                 :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      26                 :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      27                 :  * DEALINGS IN THE SOFTWARE.
      28                 :  ****************************************************************************/
      29                 : 
      30                 : #include "fit.h"
      31                 : #include "gstEndian.h"
      32                 : #include "gdal_pam.h"
      33                 : #include "cpl_string.h"
      34                 : 
      35                 : CPL_CVSID("$Id: fitdataset.cpp 23060 2011-09-05 17:58:30Z rouault $");
      36                 : 
      37                 : CPL_C_START
      38                 :  
      39                 : void  GDALRegister_FIT(void);
      40                 : CPL_C_END
      41                 : 
      42                 : #define FIT_WRITE
      43                 : 
      44                 : #define FIT_PAGE_SIZE 128
      45                 : 
      46                 : using namespace gstEndian;
      47                 : 
      48                 : /************************************************************************/
      49                 : /* ==================================================================== */
      50                 : /*        FITDataset        */
      51                 : /* ==================================================================== */
      52                 : /************************************************************************/
      53                 : 
      54                 : class FITRasterBand;
      55                 : 
      56                 : class FITDataset : public GDALPamDataset
      57                 : {
      58                 :     friend class FITRasterBand;
      59                 :     
      60                 :     VSILFILE  *fp;
      61                 :     FITinfo *info;
      62                 :     double      adfGeoTransform[6];
      63                 :     
      64                 :   public:
      65                 :     FITDataset();
      66                 :     ~FITDataset();
      67                 :     static GDALDataset *Open( GDALOpenInfo * );
      68                 : //     virtual CPLErr GetGeoTransform( double * );
      69                 : };
      70                 : 
      71                 : #ifdef FIT_WRITE
      72                 : static GDALDataset *FITCreateCopy(const char * pszFilename,
      73                 :                                   GDALDataset *poSrcDS, 
      74                 :                                   int bStrict, char ** papszOptions, 
      75                 :                                   GDALProgressFunc pfnProgress,
      76                 :                                   void * pProgressData );
      77                 : #endif // FIT_WRITE
      78                 : 
      79                 : /************************************************************************/
      80                 : /* ==================================================================== */
      81                 : /*                            FITRasterBand                             */
      82                 : /* ==================================================================== */
      83                 : /************************************************************************/
      84                 : 
      85                 : class FITRasterBand : public GDALPamRasterBand
      86                 : {
      87                 :     friend class FITDataset;
      88                 :     
      89                 :     unsigned long recordSize; // number of bytes of a single page/block/record
      90                 :     unsigned long numXBlocks; // number of pages in the X direction
      91                 :     unsigned long numYBlocks; // number of pages in the Y direction
      92                 :     unsigned long bytesPerComponent;
      93                 :     unsigned long bytesPerPixel;
      94                 :     char *tmpImage;
      95                 : 
      96                 : public:
      97                 : 
      98                 :     FITRasterBand( FITDataset *, int );
      99                 :     ~FITRasterBand();
     100                 :     
     101                 :     // should override RasterIO eventually.
     102                 :     
     103                 :     virtual CPLErr IReadBlock( int, int, void * );
     104                 : //     virtual CPLErr WriteBlock( int, int, void * ); 
     105                 :     virtual double GetMinimum( int *pbSuccess );
     106                 :     virtual double GetMaximum( int *pbSuccess );
     107                 :     virtual GDALColorInterp GetColorInterpretation();
     108                 : };
     109                 : 
     110                 : 
     111                 : /************************************************************************/
     112                 : /*                           FITRasterBand()                            */
     113                 : /************************************************************************/
     114                 : 
     115              42 : FITRasterBand::FITRasterBand( FITDataset *poDS, int nBand ) : tmpImage( NULL )
     116                 : 
     117                 : {
     118              42 :     this->poDS = poDS;
     119              42 :     this->nBand = nBand;
     120                 :     
     121                 : /* -------------------------------------------------------------------- */
     122                 : /*      Get the GDAL data type.                                         */
     123                 : /* -------------------------------------------------------------------- */
     124              42 :     eDataType = fitDataType(poDS->info->dtype);
     125                 : 
     126                 : /* -------------------------------------------------------------------- */
     127                 : /*      Get the page sizes.                                             */
     128                 : /* -------------------------------------------------------------------- */
     129              42 :     nBlockXSize = poDS->info->xPageSize;
     130              42 :     nBlockYSize = poDS->info->yPageSize;
     131                 : 
     132                 : /* -------------------------------------------------------------------- */
     133                 : /*      Caculate the values for record offset calculations.             */
     134                 : /* -------------------------------------------------------------------- */
     135              42 :     bytesPerComponent = (GDALGetDataTypeSize(eDataType) / 8);
     136              42 :     bytesPerPixel = poDS->nBands * bytesPerComponent;
     137              42 :     recordSize = bytesPerPixel * nBlockXSize * nBlockYSize;
     138                 :     numXBlocks =
     139              42 :         (unsigned long) ceil((double) poDS->info->xSize / nBlockXSize);
     140                 :     numYBlocks =
     141              42 :         (unsigned long) ceil((double) poDS->info->ySize / nBlockYSize);
     142                 : 
     143              42 :     tmpImage = (char *) malloc(recordSize);
     144              42 :     if (! tmpImage)
     145                 :         CPLError(CE_Fatal, CPLE_NotSupported, 
     146               0 :                  "FITRasterBand couldn't allocate %lu bytes", recordSize);
     147                 : 
     148                 : /* -------------------------------------------------------------------- */
     149                 : /*      Set the access flag.  For now we set it the same as the         */
     150                 : /*      whole dataset, but eventually this should take account of       */
     151                 : /*      locked channels, or read-only secondary data files.             */
     152                 : /* -------------------------------------------------------------------- */
     153                 :     /* ... */
     154              42 : }
     155                 : 
     156                 : 
     157              42 : FITRasterBand::~FITRasterBand()
     158                 : {
     159              42 :     if ( tmpImage )
     160              42 :         free ( tmpImage );
     161              42 : }
     162                 : 
     163                 : 
     164                 : /************************************************************************/
     165                 : /*                            IReadBlock()                              */
     166                 : /************************************************************************/
     167                 : 
     168                 : #define COPY_XFIRST(t) { \
     169                 :                 t *dstp = (t *) pImage; \
     170                 :                 t *srcp = (t *) tmpImage; \
     171                 :                 srcp += nBand-1; \
     172                 :                 long i = 0; \
     173                 :                 for(long y=ystart; y != ystop; y+= yinc) \
     174                 :                     for(long x=xstart; x != xstop; x+= xinc, i++) { \
     175                 :                         dstp[i] = srcp[(y * nBlockXSize + x) * \
     176                 :                                        poFIT_DS->nBands]; \
     177                 :                     } \
     178                 :     }
     179                 : 
     180                 : 
     181                 : #define COPY_YFIRST(t) { \
     182                 :                 t *dstp = (t *) pImage; \
     183                 :                 t *srcp = (t *) tmpImage; \
     184                 :                 srcp += nBand-1; \
     185                 :                 long i = 0; \
     186                 :                 for(long x=xstart; x != xstop; x+= xinc, i++) \
     187                 :                     for(long y=ystart; y != ystop; y+= yinc) { \
     188                 :                         dstp[i] = srcp[(x * nBlockYSize + y) * \
     189                 :                                        poFIT_DS->nBands]; \
     190                 :                     } \
     191                 :     }
     192                 : 
     193             700 : CPLErr FITRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
     194                 :                                   void * pImage )
     195                 : 
     196                 : {
     197             700 :     FITDataset  *poFIT_DS = (FITDataset *) poDS;
     198                 : 
     199             700 :     uint64 tilenum = 0;
     200                 : 
     201             700 :     switch (poFIT_DS->info->space) {
     202                 :     case 1:
     203                 :         // iflUpperLeftOrigin - from upper left corner
     204                 :         // scan right then down
     205             700 :         tilenum = nBlockYOff * numXBlocks + nBlockXOff;
     206             700 :         break;
     207                 :     case 2:
     208                 :         // iflUpperRightOrigin - from upper right corner
     209                 :         // scan left then down
     210               0 :         tilenum = numYBlocks * numXBlocks + (numXBlocks-1-nBlockXOff);
     211               0 :         break;
     212                 :     case 3:
     213                 :         // iflLowerRightOrigin - from lower right corner
     214                 :         // scan left then up
     215                 :         tilenum = (numYBlocks-1-nBlockYOff) * numXBlocks +
     216               0 :             (numXBlocks-1-nBlockXOff);
     217               0 :         break;
     218                 :     case 4:
     219                 :         // iflLowerLeftOrigin - from lower left corner
     220                 :         // scan right then up
     221               0 :         tilenum = (numYBlocks-1-nBlockYOff) * numXBlocks + nBlockXOff;
     222               0 :         break;
     223                 :     case 5:
     224                 :         // iflLeftUpperOrigin -* from upper left corner
     225                 :         // scan down then right
     226               0 :         tilenum = nBlockXOff * numYBlocks + nBlockYOff;
     227               0 :         break;
     228                 :     case 6:
     229                 :         // iflRightUpperOrigin - from upper right corner
     230                 :         // scan down then left
     231               0 :         tilenum = (numXBlocks-1-nBlockXOff) * numYBlocks + nBlockYOff;
     232               0 :         break;
     233                 :     case 7:
     234                 :         // iflRightLowerOrigin - from lower right corner
     235                 :         // scan up then left
     236               0 :         tilenum = nBlockXOff * numYBlocks + (numYBlocks-1-nBlockYOff);
     237               0 :         break;
     238                 :     case 8:
     239                 :         // iflLeftLowerOrigin -* from lower left corner
     240                 :         // scan up then right
     241                 :         tilenum = (numXBlocks-1-nBlockXOff) * numYBlocks +
     242               0 :             (numYBlocks-1-nBlockYOff);
     243               0 :         break;
     244                 :     default:
     245                 :         CPLError(CE_Failure, CPLE_NotSupported,
     246                 :                  "FIT - unrecognized image space %i",
     247               0 :                  poFIT_DS->info->space);
     248               0 :         tilenum = 0;
     249                 :     } // switch
     250                 : 
     251             700 :     uint64 offset = poFIT_DS->info->dataOffset + recordSize * tilenum;
     252                 : //     CPLDebug("FIT", "%i RasterBand::IReadBlock %i %i (out of %i %i) -- %i",
     253                 : //              poFIT_DS->info->space,
     254                 : //              nBlockXOff, nBlockYOff, numXBlocks, numYBlocks, tilenum);
     255                 : 
     256             700 :     if ( VSIFSeekL( poFIT_DS->fp, offset, SEEK_SET ) == -1 ) {
     257                 :         CPLError(CE_Failure, CPLE_NotSupported,
     258               0 :                  "FIT - 64bit file seek failure, handle=%p", poFIT_DS->fp );
     259               0 :       return CE_Failure;
     260                 :     }
     261                 : 
     262                 :     // XXX - should handle status
     263                 :     // fast path is single component (ll?) - no copy needed
     264                 :     char *p;
     265             700 :     int fastpath = FALSE;
     266                 : 
     267             700 :     if ((poFIT_DS->nBands == 1) && (poFIT_DS->info->space == 1)) // upper left
     268             700 :         fastpath = TRUE;
     269                 : 
     270             700 :     if (! fastpath) {
     271               0 :         VSIFReadL( tmpImage, recordSize, 1, poFIT_DS->fp );
     272                 :         // offset to correct component to swap
     273               0 :         p = (char *) tmpImage + nBand-1;
     274                 :     }
     275                 :     else {
     276             700 :         VSIFReadL( pImage, recordSize, 1, poFIT_DS->fp );
     277             700 :         p = (char *) pImage;
     278                 :     }
     279                 : 
     280                 : 
     281                 : #ifdef swapping
     282             700 :     unsigned long i = 0;
     283                 : 
     284             700 :     switch(bytesPerComponent) {
     285                 :     case 1:
     286                 :         // do nothing
     287             100 :         break;
     288                 :     case 2:
     289            1000 :         for(i=0; i < recordSize; i+= bytesPerPixel)
     290             800 :             gst_swap16(p + i);
     291             200 :         break;
     292                 :     case 4:
     293            1500 :         for(i=0; i < recordSize; i+= bytesPerPixel)
     294            1200 :             gst_swap32(p + i);
     295             300 :         break;
     296                 :     case 8:
     297             500 :         for(i=0; i < recordSize; i+= bytesPerPixel)
     298             400 :             gst_swap64(p + i);
     299             100 :         break;
     300                 :     default:
     301                 :         CPLError(CE_Failure, CPLE_NotSupported, 
     302                 :                  "FITRasterBand::IReadBlock unsupported bytesPerPixel %lu",
     303               0 :                  bytesPerComponent);
     304                 :     } // switch
     305                 : #else
     306                 :     (void) p; // avoid warnings.
     307                 : #endif // swapping
     308                 : 
     309             700 :     if (! fastpath) {
     310                 :         long xinc, yinc, xstart, ystart, xstop, ystop;
     311               0 :         if (poFIT_DS->info->space <= 4) {
     312                 :             // scan left/right first
     313                 : 
     314               0 :             switch (poFIT_DS->info->space) {
     315                 :             case 1:
     316                 :                 // iflUpperLeftOrigin - from upper left corner
     317                 :                 // scan right then down
     318               0 :                 xinc = 1;
     319               0 :                 yinc = 1;
     320               0 :                 break;
     321                 :             case 2:
     322                 :                 // iflUpperRightOrigin - from upper right corner
     323                 :                 // scan left then down
     324               0 :                 xinc = -1;
     325               0 :                 yinc = 1;
     326               0 :                 break;
     327                 :             case 3:
     328                 :                 // iflLowerRightOrigin - from lower right corner
     329                 :                 // scan left then up
     330               0 :                 xinc = -1;
     331               0 :                 yinc = -1;
     332               0 :                 break;
     333                 :             case 4:
     334                 :                 // iflLowerLeftOrigin - from lower left corner
     335                 :                 // scan right then up
     336               0 :                 xinc = 1;
     337               0 :                 yinc = -1;
     338               0 :                break;
     339                 :             default:
     340                 :                 CPLError(CE_Failure, CPLE_NotSupported,
     341                 :                          "FIT - unrecognized image space %i",
     342               0 :                          poFIT_DS->info->space);
     343               0 :                 xinc = 1;
     344               0 :                 yinc = 1;
     345                 :             } // switch
     346                 : 
     347                 : 
     348               0 :             if (xinc == 1) {
     349               0 :                 xstart = 0;
     350               0 :                 xstop = nBlockXSize;
     351                 :             }
     352                 :             else {
     353               0 :                 xstart = nBlockXSize-1;
     354               0 :                 xstop = -1;
     355                 :             }
     356               0 :             if (yinc == 1) {
     357               0 :                 ystart = 0;
     358               0 :                 ystop = nBlockYSize;
     359                 :             }
     360                 :             else {
     361               0 :                 int localBlockYSize = nBlockYSize;
     362                 :                 long maxy_full =
     363               0 :                     (long) floor(poFIT_DS->info->ySize / (double) nBlockYSize);
     364               0 :                 if (nBlockYOff >= maxy_full)
     365               0 :                     localBlockYSize = poFIT_DS->info->ySize % nBlockYSize;
     366               0 :                 ystart = localBlockYSize-1;
     367               0 :                 ystop = -1;
     368                 :             }
     369                 : 
     370               0 :             switch(bytesPerComponent) {
     371                 :             case 1:
     372               0 :                 COPY_XFIRST(char);
     373               0 :                 break;
     374                 :             case 2:
     375               0 :                 COPY_XFIRST(uint16);
     376               0 :                 break;
     377                 :             case 4:
     378               0 :                 COPY_XFIRST(uint32);
     379               0 :                 break;
     380                 :             case 8:
     381               0 :                 COPY_XFIRST(uint64);
     382               0 :                 break;
     383                 :             default:
     384                 :                 CPLError(CE_Failure, CPLE_NotSupported, 
     385                 :                          "FITRasterBand::IReadBlock unsupported "
     386               0 :                          "bytesPerComponent %lu", bytesPerComponent);
     387                 :             } // switch
     388                 : 
     389                 :         } // scan left/right first
     390                 :         else {
     391                 :             // scan up/down first
     392                 : 
     393               0 :             switch (poFIT_DS->info->space) {
     394                 :             case 5:
     395                 :                 // iflLeftUpperOrigin -* from upper left corner
     396                 :                 // scan down then right
     397               0 :                 xinc = 1;
     398               0 :                 yinc = 1;
     399               0 :                 break;
     400                 :             case 6:
     401                 :                 // iflRightUpperOrigin - from upper right corner
     402                 :                 // scan down then left
     403               0 :                 xinc = -1;
     404               0 :                 yinc = 1;
     405               0 :                 break;
     406                 :             case 7:
     407                 :                 // iflRightLowerOrigin - from lower right corner
     408                 :                 // scan up then left
     409               0 :                 xinc = -1;
     410               0 :                 yinc = -1;
     411               0 :                 break;
     412                 :             case 8:
     413                 :                 // iflLeftLowerOrigin -* from lower left corner
     414                 :                 // scan up then right
     415               0 :                 xinc = 1;
     416               0 :                 yinc = -1;
     417               0 :                 break;
     418                 :             default:
     419                 :                 CPLError(CE_Failure, CPLE_NotSupported,
     420                 :                          "FIT - unrecognized image space %i",
     421               0 :                          poFIT_DS->info->space);
     422               0 :                 xinc = 1;
     423               0 :                 yinc = 1;
     424                 :             } // switch
     425                 : 
     426               0 :             if (xinc == 1) {
     427               0 :                 xstart = 0;
     428               0 :                 xstop = nBlockXSize;
     429                 :             }
     430                 :             else {
     431               0 :                 int localBlockXSize = nBlockXSize;
     432                 :                 long maxx_full =
     433               0 :                     (long) floor(poFIT_DS->info->xSize / (double) nBlockXSize);
     434               0 :                 if (nBlockXOff >= maxx_full)
     435               0 :                     localBlockXSize = poFIT_DS->info->xSize % nBlockXSize;
     436               0 :                 xstart = localBlockXSize-1;
     437               0 :                 xstop = -1;
     438                 :             }
     439               0 :             if (yinc == 1) {
     440               0 :                 ystart = 0;
     441               0 :                 ystop = nBlockYSize;
     442                 :             }
     443                 :             else {
     444               0 :                 ystart = nBlockYSize-1;
     445               0 :                 ystop = -1;
     446                 :             }
     447                 : 
     448               0 :             switch(bytesPerComponent) {
     449                 :             case 1:
     450               0 :                 COPY_YFIRST(char);
     451               0 :                 break;
     452                 :             case 2:
     453               0 :                 COPY_YFIRST(uint16);
     454               0 :                 break;
     455                 :             case 4:
     456               0 :                 COPY_YFIRST(uint32);
     457               0 :                 break;
     458                 :             case 8:
     459               0 :                 COPY_YFIRST(uint64);
     460               0 :                 break;
     461                 :             default:
     462                 :                 CPLError(CE_Failure, CPLE_NotSupported, 
     463                 :                          "FITRasterBand::IReadBlock unsupported "
     464               0 :                          "bytesPerComponent %lu", bytesPerComponent);
     465                 :             } // switch
     466                 : 
     467                 :         } // scan up/down first
     468                 : 
     469                 :     } // ! fastpath
     470             700 :     return CE_None;
     471                 : }
     472                 : 
     473                 : #if 0
     474                 : /************************************************************************/
     475                 : /*                             ReadBlock()                              */
     476                 : /************************************************************************/
     477                 : 
     478                 : CPLErr FITRasterBand::ReadBlock( int nBlockXOff, int nBlockYOff,
     479                 :                                  void * pImage )
     480                 : 
     481                 : {
     482                 :     FITDataset  *poFIT_DS = (FITDataset *) poDS;
     483                 : 
     484                 :     
     485                 : 
     486                 :     return CE_None;
     487                 : }
     488                 : 
     489                 : /************************************************************************/
     490                 : /*                             WriteBlock()                             */
     491                 : /************************************************************************/
     492                 : 
     493                 : CPLErr FITRasterBand::WriteBlock( int nBlockXOff, int nBlockYOff,
     494                 :                                  void * pImage )
     495                 : 
     496                 : {
     497                 :     FITDataset  *poFIT_DS = (FITDataset *) poDS;
     498                 : 
     499                 :     
     500                 : 
     501                 :     return CE_None;
     502                 : }
     503                 : #endif
     504                 : 
     505                 : /************************************************************************/
     506                 : /*                             GetMinimum()                             */
     507                 : /************************************************************************/
     508                 : 
     509               0 : double FITRasterBand::GetMinimum( int *pbSuccess )
     510                 : {
     511               0 :     FITDataset *poFIT_DS = (FITDataset *) poDS;
     512                 : 
     513               0 :     if ((! poFIT_DS) || (! poFIT_DS->info))
     514               0 :         return GDALRasterBand::GetMinimum( pbSuccess );
     515                 : 
     516               0 :     if (pbSuccess)
     517               0 :         *pbSuccess = TRUE;
     518                 : 
     519               0 :     if (poFIT_DS->info->version &&
     520                 :         EQUALN((const char *) &(poFIT_DS->info->version), "02", 2)) {
     521               0 :         return poFIT_DS->info->minValue;
     522                 :     }
     523                 :     else {
     524               0 :         return GDALRasterBand::GetMinimum( pbSuccess );
     525                 :     }
     526                 : }
     527                 : 
     528                 : /************************************************************************/
     529                 : /*                             GetMaximum()                             */
     530                 : /************************************************************************/
     531                 : 
     532               0 : double FITRasterBand::GetMaximum( int *pbSuccess )
     533                 : {
     534               0 :     FITDataset *poFIT_DS = (FITDataset *) poDS;
     535                 : 
     536               0 :     if ((! poFIT_DS) || (! poFIT_DS->info))
     537               0 :         return GDALRasterBand::GetMaximum( pbSuccess );
     538                 : 
     539               0 :     if (pbSuccess)
     540               0 :         *pbSuccess = TRUE;
     541                 : 
     542               0 :     if (EQUALN((const char *) &poFIT_DS->info->version, "02", 2)) {
     543               0 :         return poFIT_DS->info->maxValue;
     544                 :     }
     545                 :     else {
     546               0 :         return GDALRasterBand::GetMaximum( pbSuccess );
     547                 :     }
     548                 : }
     549                 : 
     550                 : /************************************************************************/
     551                 : /*                       GetColorInterpretation()                       */
     552                 : /************************************************************************/
     553                 : 
     554              23 : GDALColorInterp FITRasterBand::GetColorInterpretation()
     555                 : {
     556              23 :     FITDataset  *poFIT_DS = (FITDataset *) poDS;
     557                 : 
     558              23 :     if ((! poFIT_DS) || (! poFIT_DS->info))
     559               0 :         return GCI_Undefined;
     560                 : 
     561              23 :     switch(poFIT_DS->info->cm) {
     562                 :     case 1: // iflNegative - inverted luminance (min value is white)
     563                 :         CPLError( CE_Warning, CPLE_NotSupported, 
     564               0 :                   "FIT - color model Negative not supported - ignoring model");
     565               0 :             return GCI_Undefined;
     566                 : 
     567                 :     case 2: // iflLuminance - luminance
     568              14 :         if (poFIT_DS->nBands != 1) {
     569                 :             CPLError( CE_Failure, CPLE_NotSupported, 
     570                 :                       "FIT - color model Luminance mismatch with %i bands",
     571               0 :                       poFIT_DS->nBands);
     572               0 :             return GCI_Undefined;
     573                 :         }
     574              14 :         switch (nBand) {
     575                 :         case 1:
     576              14 :             return GCI_GrayIndex;
     577                 :         default:
     578                 :             CPLError( CE_Failure, CPLE_NotSupported, 
     579               0 :                       "FIT - color model Luminance unknown band %i", nBand);
     580               0 :             return GCI_Undefined;
     581                 :         } // switch nBand
     582                 : 
     583                 :     case 3: // iflRGB - full color (Red, Green, Blue triplets)
     584               3 :         if (poFIT_DS->nBands != 3) {
     585                 :             CPLError( CE_Failure, CPLE_NotSupported, 
     586                 :                       "FIT - color model RGB mismatch with %i bands",
     587               0 :                       poFIT_DS->nBands);
     588               0 :             return GCI_Undefined;
     589                 :         }
     590               3 :         switch (nBand) {
     591                 :         case 1:
     592               1 :             return GCI_RedBand;
     593                 :         case 2:
     594               1 :             return GCI_GreenBand;
     595                 :         case 3:
     596               1 :             return GCI_BlueBand;
     597                 :         default:
     598                 :             CPLError( CE_Failure, CPLE_NotSupported, 
     599               0 :                       "FIT - color model RGB unknown band %i", nBand);
     600               0 :             return GCI_Undefined;
     601                 :         } // switch nBand
     602                 : 
     603                 :     case 4: // iflRGBPalette - color mapped values
     604                 :         CPLError( CE_Warning, CPLE_NotSupported, 
     605                 :                   "FIT - color model  RGBPalette not supported - "
     606               0 :                   "ignoring model");
     607               0 :             return GCI_Undefined;
     608                 : 
     609                 :     case 5: // iflRGBA - full color with transparency (alpha channel)
     610               4 :         if (poFIT_DS->nBands != 4) {
     611                 :             CPLError( CE_Failure, CPLE_NotSupported, 
     612                 :                       "FIT - color model RGBA mismatch with %i bands",
     613               0 :                       poFIT_DS->nBands);
     614               0 :             return GCI_Undefined;
     615                 :         }
     616               4 :         switch (nBand) {
     617                 :         case 1:
     618               1 :             return GCI_RedBand;
     619                 :         case 2:
     620               1 :             return GCI_GreenBand;
     621                 :         case 3:
     622               1 :             return GCI_BlueBand;
     623                 :         case 4:
     624               1 :             return GCI_AlphaBand;
     625                 :         default:
     626                 :             CPLError( CE_Failure, CPLE_NotSupported, 
     627               0 :                       "FIT - color model RGBA unknown band %i", nBand);
     628               0 :             return GCI_Undefined;
     629                 :         } // switch nBand
     630                 : 
     631                 :     case 6: // iflHSV - Hue, Saturation, Value
     632               0 :         if (poFIT_DS->nBands != 3) {
     633                 :             CPLError( CE_Failure, CPLE_NotSupported, 
     634                 :                       "FIT - color model HSV mismatch with %i bands",
     635               0 :                       poFIT_DS->nBands);
     636               0 :             return GCI_Undefined;
     637                 :         }
     638               0 :         switch (nBand) {
     639                 :         case 1:
     640               0 :             return GCI_HueBand;
     641                 :         case 2:
     642               0 :             return GCI_SaturationBand;
     643                 :         case 3:
     644               0 :             return GCI_LightnessBand;
     645                 :         default:
     646                 :             CPLError( CE_Failure, CPLE_NotSupported, 
     647               0 :                       "FIT - color model HSV unknown band %i", nBand);
     648               0 :             return GCI_Undefined;
     649                 :         } // switch nBand
     650                 : 
     651                 :     case 7: // iflCMY - Cyan, Magenta, Yellow
     652               0 :         if (poFIT_DS->nBands != 3) {
     653                 :             CPLError( CE_Failure, CPLE_NotSupported, 
     654                 :                       "FIT - color model CMY mismatch with %i bands",
     655               0 :                       poFIT_DS->nBands);
     656               0 :             return GCI_Undefined;
     657                 :         }
     658               0 :         switch (nBand) {
     659                 :         case 1:
     660               0 :             return GCI_CyanBand;
     661                 :         case 2:
     662               0 :             return GCI_MagentaBand;
     663                 :         case 3:
     664               0 :             return GCI_YellowBand;
     665                 :         default:
     666                 :             CPLError( CE_Failure, CPLE_NotSupported, 
     667               0 :                       "FIT - color model CMY unknown band %i", nBand);
     668               0 :             return GCI_Undefined;
     669                 :         } // switch nBand
     670                 : 
     671                 :     case 8: // iflCMYK - Cyan, Magenta, Yellow, Black
     672               0 :         if (poFIT_DS->nBands != 4) {
     673                 :             CPLError( CE_Failure, CPLE_NotSupported, 
     674                 :                       "FIT - color model CMYK mismatch with %i bands",
     675               0 :                       poFIT_DS->nBands);
     676               0 :             return GCI_Undefined;
     677                 :         }
     678               0 :         switch (nBand) {
     679                 :         case 1:
     680               0 :             return GCI_CyanBand;
     681                 :         case 2:
     682               0 :             return GCI_MagentaBand;
     683                 :         case 3:
     684               0 :             return GCI_YellowBand;
     685                 :         case 4:
     686               0 :             return GCI_BlackBand;
     687                 :         default:
     688                 :             CPLError( CE_Failure, CPLE_NotSupported, 
     689               0 :                       "FIT - color model CMYK unknown band %i", nBand);
     690               0 :             return GCI_Undefined;
     691                 :         } // switch nBand
     692                 : 
     693                 :     case 9: // iflBGR - full color (ordered Blue, Green, Red)
     694               0 :         if (poFIT_DS->nBands != 3) {
     695                 :             CPLError( CE_Failure, CPLE_NotSupported, 
     696                 :                       "FIT - color model BGR mismatch with %i bands",
     697               0 :                       poFIT_DS->nBands);
     698               0 :             return GCI_Undefined;
     699                 :         }
     700               0 :         switch (nBand) {
     701                 :         case 1:
     702               0 :             return GCI_BlueBand;
     703                 :         case 2:
     704               0 :             return GCI_GreenBand;
     705                 :         case 3:
     706               0 :             return GCI_RedBand;
     707                 :         default:
     708                 :             CPLError( CE_Failure, CPLE_NotSupported, 
     709               0 :                       "FIT - color model BGR unknown band %i", nBand);
     710               0 :             return GCI_Undefined;
     711                 :         } // switch nBand
     712                 : 
     713                 :     case 10: // iflABGR - Alpha, Blue, Green, Red (SGI frame buffers)
     714               0 :         if (poFIT_DS->nBands != 4) {
     715                 :             CPLError( CE_Failure, CPLE_NotSupported, 
     716                 :                       "FIT - color model ABGR mismatch with %i bands",
     717               0 :                       poFIT_DS->nBands);
     718               0 :             return GCI_Undefined;
     719                 :         }
     720               0 :         switch (nBand) {
     721                 :         case 1:
     722               0 :             return GCI_AlphaBand;
     723                 :         case 2:
     724               0 :             return GCI_BlueBand;
     725                 :         case 3:
     726               0 :             return GCI_GreenBand;
     727                 :         case 4:
     728               0 :             return GCI_RedBand;
     729                 :         default:
     730                 :             CPLError( CE_Failure, CPLE_NotSupported, 
     731               0 :                       "FIT - color model ABGR unknown band %i", nBand);
     732               0 :             return GCI_Undefined;
     733                 :         } // switch nBand
     734                 : 
     735                 :     case 11: // iflMultiSpectral - multi-spectral data, arbitrary number of
     736                 :         // chans
     737               0 :         return GCI_Undefined;
     738                 : 
     739                 :     case 12: // iflYCC PhotoCD color model (Luminance, Chrominance)
     740                 :         CPLError( CE_Warning, CPLE_NotSupported, 
     741               0 :                   "FIT - color model YCC not supported - ignoring model");
     742               0 :             return GCI_Undefined;
     743                 : 
     744                 :     case 13: // iflLuminanceAlpha - Luminance plus alpha
     745               1 :         if (poFIT_DS->nBands != 2) {
     746                 :             CPLError( CE_Failure, CPLE_NotSupported, 
     747                 :                       "FIT - color model LuminanceAlpha mismatch with "
     748                 :                       "%i bands",
     749               0 :                       poFIT_DS->nBands);
     750               0 :             return GCI_Undefined;
     751                 :         }
     752               1 :         switch (nBand) {
     753                 :         case 1:
     754               1 :             return GCI_GrayIndex;
     755                 :         case 2:
     756               0 :             return GCI_AlphaBand;
     757                 :         default:
     758                 :             CPLError( CE_Failure, CPLE_NotSupported, 
     759                 :                       "FIT - color model LuminanceAlpha unknown band %i",
     760               0 :                       nBand);
     761               0 :             return GCI_Undefined;
     762                 :         } // switch nBand
     763                 : 
     764                 :     default:
     765                 :         CPLError( CE_Warning, CPLE_NotSupported, 
     766                 :                   "FIT - unrecognized color model %i - ignoring model",
     767               1 :                   poFIT_DS->info->cm);
     768               1 :         return GCI_Undefined;
     769                 :     } // switch
     770                 : }
     771                 : 
     772                 : /************************************************************************/
     773                 : /*                             FITDataset()                             */
     774                 : /************************************************************************/
     775                 : 
     776              32 : FITDataset::FITDataset() : fp( NULL ), info( NULL )
     777                 : {
     778                 : 
     779              32 :     adfGeoTransform[0] = 0.0; // x origin (top left corner)
     780              32 :     adfGeoTransform[1] = 1.0; // x pixel size
     781              32 :     adfGeoTransform[2] = 0.0;
     782                 : 
     783              32 :     adfGeoTransform[3] = 0.0; // y origin (top left corner)
     784              32 :     adfGeoTransform[4] = 0.0;
     785              32 :     adfGeoTransform[5] = 1.0; // y pixel size
     786              32 : }
     787                 : 
     788                 : /************************************************************************/
     789                 : /*                             ~FITDataset()                             */
     790                 : /************************************************************************/
     791                 : 
     792              32 : FITDataset::~FITDataset()
     793                 : {
     794              32 :     FlushCache();
     795              32 :     if (info)
     796              32 :         delete(info);
     797              32 :     if(fp)
     798              32 :         VSIFCloseL(fp);
     799              32 : }
     800                 : 
     801                 : // simple guard object to delete memory 
     802                 : // when the guard goes out of scope
     803                 : template< class T >
     804                 : class DeleteGuard
     805                 : {
     806                 : public:
     807              32 :     DeleteGuard( T *p ) : _ptr( p ) { }
     808              32 :     ~DeleteGuard()
     809                 :     {
     810              32 :       delete _ptr;
     811              32 :     }
     812                 : 
     813              32 :     T *take()
     814                 :     {
     815              32 :         T *tmp = _ptr;
     816              32 :       _ptr = 0;
     817              32 :       return tmp;
     818                 :     }
     819                 : 
     820                 : private:
     821                 :     T *_ptr;
     822                 :   // prevent default copy constructor and assignment operator
     823                 :     DeleteGuard( const DeleteGuard & );  
     824                 :     DeleteGuard &operator=( const DeleteGuard & );
     825                 : };
     826                 : 
     827                 : // simple guard object to free memory 
     828                 : // when the guard goes out of scope
     829                 : template< class T >
     830                 : class FreeGuard
     831                 : {
     832                 : public:
     833              40 :     FreeGuard( T *p ) : _ptr( p ) { }
     834              40 :     ~FreeGuard()
     835                 :     {
     836              40 :       if ( _ptr )
     837              40 :       free( _ptr );
     838              40 :     }
     839                 : 
     840                 :     T *take()
     841                 :     {
     842                 :         T *tmp = _ptr;
     843                 :       _ptr = 0;
     844                 :       return tmp;
     845                 :     }
     846                 : 
     847                 : private:
     848                 :     T *_ptr;
     849                 :   // prevent default copy constructor and assignment operator
     850                 :     FreeGuard( const FreeGuard & );  
     851                 :     FreeGuard &operator=( const FreeGuard & );
     852                 : };
     853                 : 
     854                 : /************************************************************************/
     855                 : /*                                Open()                                */
     856                 : /************************************************************************/
     857                 : 
     858           11435 : GDALDataset *FITDataset::Open( GDALOpenInfo * poOpenInfo )
     859                 : {
     860                 : /* -------------------------------------------------------------------- */
     861                 : /*  First we check to see if the file has the expected header */
     862                 : /*  bytes.                */    
     863                 : /* -------------------------------------------------------------------- */
     864                 : 
     865           11435 :     if( poOpenInfo->nHeaderBytes < 5 )
     866           10600 :         return NULL;
     867                 : 
     868                 : 
     869             835 :     if( !EQUALN((const char *) poOpenInfo->pabyHeader, "IT01", 4) &&
     870                 :         !EQUALN((const char *) poOpenInfo->pabyHeader, "IT02", 4) )
     871             803 :         return NULL;
     872                 : 
     873              32 :     if( poOpenInfo->eAccess == GA_Update )
     874                 :     {
     875                 :         CPLError( CE_Failure, CPLE_NotSupported, 
     876                 :                   "The FIT driver does not support update access to existing"
     877               0 :                   " files.\n" );
     878               0 :         return NULL;
     879                 :     }
     880                 : 
     881                 : /* -------------------------------------------------------------------- */
     882                 : /*      Create a corresponding GDALDataset.                             */
     883                 : /* -------------------------------------------------------------------- */
     884                 :     FITDataset  *poDS;
     885                 : 
     886              32 :     poDS = new FITDataset();
     887              32 :     DeleteGuard<FITDataset> guard( poDS );
     888                 : 
     889                 :   // re-open file for large file (64bit) access
     890              32 :     if ( poOpenInfo->eAccess == GA_ReadOnly )
     891              32 :   poDS->fp = VSIFOpenL( poOpenInfo->pszFilename, "rb" );
     892                 :     else
     893               0 :   poDS->fp = VSIFOpenL( poOpenInfo->pszFilename, "r+b" );
     894                 : 
     895              32 :     if ( !poDS->fp ) {
     896                 :       CPLError( CE_Failure, CPLE_OpenFailed,
     897                 :     "Failed to re-open %s with FIT driver.\n",
     898               0 :     poOpenInfo->pszFilename );
     899               0 :       return NULL;
     900                 :     }
     901              32 :     poDS->eAccess = poOpenInfo->eAccess;
     902                 : 
     903                 : 
     904              32 :     poDS->info = new FITinfo;
     905              32 :     FITinfo *info = poDS->info;
     906                 : 
     907                 : /* -------------------------------------------------------------------- */
     908                 : /*      Read other header values.                                       */
     909                 : /* -------------------------------------------------------------------- */
     910              32 :     FIThead02 *head = (FIThead02 *) poOpenInfo->pabyHeader;
     911                 : 
     912                 :     // extract the image attributes from the file header
     913              32 :     if (EQUALN((const char *) &head->version, "02", 2)) {
     914                 :         // incomplete header
     915              32 :         if( poOpenInfo->nHeaderBytes < (signed) sizeof(FIThead02) )
     916               0 :             return NULL;
     917                 : 
     918              32 :         CPLDebug("FIT", "Loading file with header version 02");
     919                 : 
     920              32 :         gst_swapb(head->minValue);
     921              32 :   info->minValue = head->minValue;
     922              32 :         gst_swapb(head->maxValue);
     923              32 :   info->maxValue = head->maxValue;
     924              32 :         gst_swapb(head->dataOffset);
     925              32 :   info->dataOffset = head->dataOffset;
     926                 : 
     927              32 :         info->userOffset = sizeof(FIThead02);
     928                 :     }
     929               0 :     else if (EQUALN((const char *) &head->version, "01", 2)) {
     930                 :         // incomplete header
     931               0 :         if( poOpenInfo->nHeaderBytes < (signed) sizeof(FIThead01) )
     932               0 :             return NULL;
     933                 : 
     934               0 :         CPLDebug("FIT", "Loading file with header version 01");
     935                 : 
     936                 :         // map old style header into new header structure
     937               0 :   FIThead01* head01 = (FIThead01*)head;
     938               0 :         gst_swapb(head->dataOffset);
     939               0 :   info->dataOffset = head01->dataOffset;
     940                 : 
     941               0 :         info->userOffset = sizeof(FIThead01);
     942                 :     }
     943                 :     else {
     944                 :         // unrecognized header version
     945                 :         CPLError( CE_Failure, CPLE_NotSupported, 
     946                 :                   "FIT - unsupported header version %.2s\n",
     947               0 :                   (const char*) &head->version);
     948               0 :         return NULL;
     949                 :     }
     950                 : 
     951                 :     CPLDebug("FIT", "userOffset %i, dataOffset %i",
     952              32 :              info->userOffset, info->dataOffset);
     953                 : 
     954              32 :     info->magic = head->magic;
     955              32 :     info->version = head->version;
     956                 : 
     957              32 :     gst_swapb(head->xSize);
     958              32 :     info->xSize = head->xSize;
     959              32 :     gst_swapb(head->ySize);
     960              32 :     info->ySize = head->ySize;
     961              32 :     gst_swapb(head->zSize);
     962              32 :     info->zSize = head->zSize;
     963              32 :     gst_swapb(head->cSize);
     964              32 :     info->cSize = head->cSize;
     965              32 :     gst_swapb(head->dtype);
     966              32 :     info->dtype = head->dtype;
     967              32 :     gst_swapb(head->order);
     968              32 :     info->order = head->order;
     969              32 :     gst_swapb(head->space);
     970              32 :     info->space = head->space;
     971              32 :     gst_swapb(head->cm);
     972              32 :     info->cm = head->cm;
     973              32 :     gst_swapb(head->xPageSize);
     974              32 :     info->xPageSize = head->xPageSize;
     975              32 :     gst_swapb(head->yPageSize);
     976              32 :     info->yPageSize = head->yPageSize;
     977              32 :     gst_swapb(head->zPageSize);
     978              32 :     info->zPageSize = head->zPageSize;
     979              32 :     gst_swapb(head->cPageSize);
     980              32 :     info->cPageSize = head->cPageSize;
     981                 : 
     982                 :     CPLDebug("FIT", "size %i %i %i %i, pageSize %i %i %i %i",
     983                 :              info->xSize, info->ySize, info->zSize, info->cSize, 
     984                 :              info->xPageSize, info->yPageSize, info->zPageSize,
     985              32 :              info->cPageSize);
     986                 : 
     987                 :     CPLDebug("FIT", "dtype %i order %i space %i cm %i",
     988              32 :              info->dtype, info->order, info->space, info->cm);
     989                 : 
     990                 :     /**************************/
     991                 : 
     992              32 :     poDS->nRasterXSize = head->xSize;
     993              32 :     poDS->nRasterYSize = head->ySize;
     994              32 :     poDS->nBands = head->cSize;
     995                 : 
     996                 : /* -------------------------------------------------------------------- */
     997                 : /*      Check if 64 bit seek is needed.                                 */
     998                 : /* -------------------------------------------------------------------- */
     999                 :     uint64 bytesPerComponent =
    1000              32 :         (GDALGetDataTypeSize(fitDataType(poDS->info->dtype)) / 8);
    1001              32 :     uint64 bytesPerPixel = head->cSize * bytesPerComponent;
    1002                 :     uint64 recordSize = bytesPerPixel * head->xPageSize *
    1003              32 :         head->yPageSize;
    1004                 :     uint64 numXBlocks =
    1005              32 :         (uint64) ceil((double) head->xSize / head->xPageSize);
    1006                 :     uint64 numYBlocks =
    1007              32 :         (uint64) ceil((double) head->ySize / head->yPageSize);
    1008                 : 
    1009              32 :     uint64 maxseek = recordSize * numXBlocks * numYBlocks;
    1010                 : 
    1011                 : //     CPLDebug("FIT", "(sizeof %i) max seek %llx ==> %llx\n", sizeof(uint64),
    1012                 : //              maxseek, maxseek >> 31);
    1013              32 :     if (maxseek >> 31) // signed long
    1014                 : #ifdef VSI_LARGE_API_SUPPORTED
    1015               0 :         CPLDebug("FIT", "Using 64 bit version of fseek");
    1016                 : #else
    1017                 :         CPLError(CE_Fatal, CPLE_NotSupported, 
    1018                 :                  "FIT - need 64 bit version of fseek");
    1019                 : #endif
    1020                 : 
    1021                 : /* -------------------------------------------------------------------- */
    1022                 : /*      Verify all "unused" header values.                              */
    1023                 : /* -------------------------------------------------------------------- */
    1024                 : 
    1025              32 :     if( info->zSize != 1 )
    1026                 :     {
    1027                 :         CPLError( CE_Failure, CPLE_NotSupported, 
    1028               0 :                   "FIT driver - unsupported zSize %i\n", info->zSize);
    1029               0 :         return NULL;
    1030                 :     }
    1031                 : 
    1032              32 :     if( info->order != 1 ) // interleaved - RGBRGB
    1033                 :     {
    1034                 :         CPLError( CE_Failure, CPLE_NotSupported, 
    1035               0 :                   "FIT driver - unsupported order %i\n", info->order);
    1036               0 :         return NULL;
    1037                 :     }
    1038                 : 
    1039              32 :     if( info->zPageSize != 1 )
    1040                 :     {
    1041                 :         CPLError( CE_Failure, CPLE_NotSupported, 
    1042               0 :                   "FIT driver - unsupported zPageSize %i\n", info->zPageSize);
    1043               0 :         return NULL;
    1044                 :     }
    1045                 : 
    1046              32 :     if( info->cPageSize != info->cSize )
    1047                 :     {
    1048                 :         CPLError( CE_Failure, CPLE_NotSupported, 
    1049                 :                   "FIT driver - unsupported cPageSize %i (!= %i)\n",
    1050               0 :                   info->cPageSize, info->cSize);
    1051               0 :         return NULL;
    1052                 :     }
    1053                 : 
    1054                 : /* -------------------------------------------------------------------- */
    1055                 : /*      Create band information objects.                                */
    1056                 : /* -------------------------------------------------------------------- */
    1057              74 :     for( int i = 0; i < poDS->nBands; i++ )
    1058                 :     {
    1059              42 :         poDS->SetBand( i+1,  new FITRasterBand( poDS, i+1 ) ) ;
    1060                 :     }
    1061                 : 
    1062                 : /* -------------------------------------------------------------------- */
    1063                 : /*      Initialize any PAM information.                                 */
    1064                 : /* -------------------------------------------------------------------- */
    1065              32 :     poDS->SetDescription( poOpenInfo->pszFilename );
    1066              32 :     poDS->TryLoadXML();
    1067                 : 
    1068                 : /* -------------------------------------------------------------------- */
    1069                 : /*      Check for external overviews.                                   */
    1070                 : /* -------------------------------------------------------------------- */
    1071              32 :     poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename, poOpenInfo->papszSiblingFiles );
    1072                 : 
    1073              32 :     return guard.take();
    1074                 : }
    1075                 : 
    1076                 : /************************************************************************/
    1077                 : /*                           FITCreateCopy()                            */
    1078                 : /************************************************************************/
    1079                 : 
    1080                 : #ifdef FIT_WRITE
    1081              25 : static GDALDataset *FITCreateCopy(const char * pszFilename,
    1082                 :                                   GDALDataset *poSrcDS, 
    1083                 :                                   int bStrict, char ** papszOptions, 
    1084                 :                                   GDALProgressFunc pfnProgress,
    1085                 :                                   void * pProgressData )
    1086                 : {
    1087              25 :     CPLDebug("FIT", "CreateCopy %s - %i", pszFilename, bStrict);
    1088                 : 
    1089              25 :     int nBands = poSrcDS->GetRasterCount();
    1090              25 :     if (nBands == 0)
    1091                 :     {
    1092                 :         CPLError( CE_Failure, CPLE_NotSupported, 
    1093               1 :                   "FIT driver does not support source dataset with zero band.\n");
    1094               1 :         return NULL;
    1095                 :     }
    1096                 : 
    1097                 : /* -------------------------------------------------------------------- */
    1098                 : /*      Create the dataset.                                             */
    1099                 : /* -------------------------------------------------------------------- */
    1100                 :     VSILFILE  *fpImage;
    1101                 : 
    1102              24 :     if( !pfnProgress( 0.0, NULL, pProgressData ) )
    1103                 :     {
    1104               0 :         CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
    1105               0 :         return NULL;
    1106                 :     }
    1107                 : 
    1108              24 :     fpImage = VSIFOpenL( pszFilename, "wb" );
    1109              24 :     if( fpImage == NULL )
    1110                 :     {
    1111                 :         CPLError( CE_Failure, CPLE_OpenFailed, 
    1112                 :                   "FIT - unable to create file %s.\n", 
    1113               2 :                   pszFilename );
    1114               2 :         return NULL;
    1115                 :     }
    1116                 : 
    1117                 : /* -------------------------------------------------------------------- */
    1118                 : /*      Generate header.                                                */
    1119                 : /* -------------------------------------------------------------------- */
    1120                 :     // XXX - should FIT_PAGE_SIZE be based on file page size ??
    1121              22 :     int size = MAX(sizeof(FIThead02), FIT_PAGE_SIZE);
    1122              22 :     FIThead02 *head = (FIThead02 *) malloc(size);
    1123              22 :     FreeGuard<FIThead02> guardHead( head );
    1124                 : 
    1125                 :     // clean header so padding (past real header) is all zeros
    1126              22 :     memset( head, 0, size );
    1127                 : 
    1128              22 :     strncpy((char *) &head->magic, "IT", 2);
    1129              22 :     strncpy((char *) &head->version, "02", 2);
    1130                 : 
    1131              22 :     head->xSize = poSrcDS->GetRasterXSize();
    1132              22 :     gst_swapb(head->xSize);
    1133              22 :     head->ySize = poSrcDS->GetRasterYSize();
    1134              22 :     gst_swapb(head->ySize);
    1135              22 :     head->zSize = 1;
    1136              22 :     gst_swapb(head->zSize);
    1137                 : 
    1138              22 :     head->cSize = nBands;
    1139              22 :     gst_swapb(head->cSize);
    1140                 : 
    1141              22 :     GDALRasterBand *firstBand = poSrcDS->GetRasterBand(1);
    1142              22 :     if (! firstBand) {
    1143               0 :         VSIFCloseL(fpImage);
    1144               0 :         return NULL;
    1145                 :     }
    1146                 : 
    1147              22 :     head->dtype = fitGetDataType(firstBand->GetRasterDataType());
    1148              22 :     if (! head->dtype) {
    1149               4 :         VSIFCloseL(fpImage);
    1150               4 :         return NULL;
    1151                 :     }
    1152              18 :     gst_swapb(head->dtype);
    1153              18 :     head->order = 1; // interleaved - RGBRGB
    1154              18 :     gst_swapb(head->order);
    1155              18 :     head->space = 1; // upper left
    1156              18 :     gst_swapb(head->space);
    1157                 : 
    1158                 :     // XXX - need to check all bands
    1159              18 :     head->cm = fitGetColorModel(firstBand->GetColorInterpretation(), nBands);
    1160              18 :     gst_swapb(head->cm);
    1161                 : 
    1162                 :     int blockX, blockY;
    1163              18 :     firstBand->GetBlockSize(&blockX, &blockY);
    1164              18 :     CPLDebug("FIT write", "inherited block size %ix%i", blockX, blockY);
    1165                 : 
    1166              18 :     if( CSLFetchNameValue(papszOptions,"PAGESIZE") != NULL )
    1167                 :     {
    1168               7 :         const char *str = CSLFetchNameValue(papszOptions,"PAGESIZE");
    1169                 :         int newBlockX, newBlockY;
    1170               7 :         sscanf(str, "%i,%i", &newBlockX, &newBlockY);
    1171              14 :         if (newBlockX && newBlockY) {
    1172               7 :             blockX = newBlockX;
    1173               7 :             blockY = newBlockY;
    1174                 :         }
    1175                 :         else {
    1176                 :             CPLError(CE_Failure, CPLE_OpenFailed, 
    1177               0 :                      "FIT - Unable to parse option PAGESIZE values [%s]", str);
    1178                 :         }
    1179                 :     }
    1180                 : 
    1181                 :     // XXX - need to do lots of checking of block size
    1182                 :     // * provide ability to override block size with options
    1183                 :     // * handle non-square block size (like scanline)
    1184                 :     //   - probably default from non-tiled image - have default block size
    1185                 :     // * handle block size bigger than image size
    1186                 :     // * undesirable block size (non power of 2, others?)
    1187                 :     // * mismatched block sizes for different bands
    1188                 :     // * image that isn't even pages (ie. partially empty pages at edge)
    1189              18 :     CPLDebug("FIT write", "using block size %ix%i", blockX, blockY);
    1190                 : 
    1191              18 :     head->xPageSize = blockX;
    1192              18 :     gst_swapb(head->xPageSize);
    1193              18 :     head->yPageSize = blockY;
    1194              18 :     gst_swapb(head->yPageSize);
    1195              18 :     head->zPageSize = 1;
    1196              18 :     gst_swapb(head->zPageSize);
    1197              18 :     head->cPageSize = nBands;
    1198              18 :     gst_swapb(head->cPageSize);
    1199                 : 
    1200                 :     // XXX - need to check all bands
    1201              18 :     head->minValue = firstBand->GetMinimum();
    1202              18 :     gst_swapb(head->minValue);
    1203                 :     // XXX - need to check all bands
    1204              18 :     head->maxValue = firstBand->GetMaximum();
    1205              18 :     gst_swapb(head->maxValue);
    1206              18 :     head->dataOffset = size;
    1207              18 :     gst_swapb(head->dataOffset);
    1208                 : 
    1209              18 :     VSIFWriteL(head, size, 1, fpImage);
    1210                 : 
    1211                 : /* -------------------------------------------------------------------- */
    1212                 : /*      Loop over image, copying image data.                            */
    1213                 : /* -------------------------------------------------------------------- */
    1214                 :     unsigned long bytesPerComponent =
    1215              18 :         (GDALGetDataTypeSize(firstBand->GetRasterDataType()) / 8);
    1216              18 :     unsigned long bytesPerPixel = nBands * bytesPerComponent;
    1217                 : 
    1218              18 :     unsigned long pageBytes = blockX * blockY * bytesPerPixel;
    1219              18 :     char *output = (char *) malloc(pageBytes);
    1220              18 :     if (! output)
    1221                 :         CPLError(CE_Fatal, CPLE_NotSupported, 
    1222               0 :                  "FITRasterBand couldn't allocate %lu bytes", pageBytes);
    1223              18 :     FreeGuard<char> guardOutput( output );
    1224                 : 
    1225              18 :     long maxx = (long) ceil(poSrcDS->GetRasterXSize() / (double) blockX);
    1226              18 :     long maxy = (long) ceil(poSrcDS->GetRasterYSize() / (double) blockY);
    1227              18 :     long maxx_full = (long) floor(poSrcDS->GetRasterXSize() / (double) blockX);
    1228              18 :     long maxy_full = (long) floor(poSrcDS->GetRasterYSize() / (double) blockY);
    1229                 : 
    1230              18 :     CPLDebug("FIT", "about to write %ld x %ld blocks", maxx, maxy);
    1231                 : 
    1232              99 :     for(long y=0; y < maxy; y++)
    1233             792 :         for(long x=0; x < maxx; x++) {
    1234             711 :             long readX = blockX;
    1235             711 :             long readY = blockY;
    1236             711 :             int do_clean = FALSE;
    1237                 : 
    1238                 :             // handle cases where image size isn't an exact multiple
    1239                 :             // of page size
    1240             711 :             if (x >= maxx_full) {
    1241               0 :                 readX = poSrcDS->GetRasterXSize() % blockX;
    1242               0 :                 do_clean = TRUE;
    1243                 :             }
    1244             711 :             if (y >= maxy_full) {
    1245               0 :                 readY = poSrcDS->GetRasterYSize() % blockY;
    1246               0 :                 do_clean = TRUE;
    1247                 :             }
    1248                 : 
    1249                 :             // clean out image if only doing partial reads
    1250             711 :             if (do_clean)
    1251               0 :                 memset( output, 0, pageBytes );
    1252                 : 
    1253            1432 :             for( int iBand = 0; iBand < nBands; iBand++ ) {
    1254             721 :                 GDALRasterBand * poBand = poSrcDS->GetRasterBand( iBand+1 );
    1255                 :                 CPLErr eErr =
    1256                 :                     poBand->RasterIO( GF_Read, // eRWFlag
    1257                 :                                       x * blockX, // nXOff
    1258                 :                                       y * blockY, // nYOff
    1259                 :                                       readX, // nXSize
    1260                 :                                       readY, // nYSize
    1261                 :                                       output + iBand * bytesPerComponent,
    1262                 :                                       // pData
    1263                 :                                       blockX, // nBufXSize
    1264                 :                                       blockY, // nBufYSize
    1265                 :                                       firstBand->GetRasterDataType(),
    1266                 :                                       // eBufType
    1267                 :                                       bytesPerPixel, // nPixelSpace
    1268             721 :                                       bytesPerPixel * blockX); // nLineSpace
    1269             721 :                 if (eErr != CE_None)
    1270                 :                     CPLError(CE_Failure, CPLE_FileIO, 
    1271               0 :                              "FIT write - CreateCopy got read error %i", eErr);
    1272                 :             } // for iBand
    1273                 : 
    1274                 : #ifdef swapping
    1275             711 :             char *p = output;
    1276                 :             unsigned long i;
    1277             711 :             switch(bytesPerComponent) {
    1278                 :             case 1:
    1279                 :                 // do nothing
    1280             105 :                 break;
    1281                 :             case 2:
    1282            1202 :                 for(i=0; i < pageBytes; i+= bytesPerComponent)
    1283            1000 :                     gst_swap16(p + i);
    1284             202 :                 break;
    1285                 :             case 4:
    1286            1803 :                 for(i=0; i < pageBytes; i+= bytesPerComponent)
    1287            1500 :                     gst_swap32(p + i);
    1288             303 :                 break;
    1289                 :             case 8:
    1290             601 :                 for(i=0; i < pageBytes; i+= bytesPerComponent)
    1291             500 :                     gst_swap64(p + i);
    1292             101 :                 break;
    1293                 :             default:
    1294                 :                 CPLError(CE_Failure, CPLE_NotSupported, 
    1295                 :                          "FIT write - unsupported bytesPerPixel %lu",
    1296               0 :                          bytesPerComponent);
    1297                 :             } // switch
    1298                 : #endif // swapping
    1299                 :             
    1300             711 :             VSIFWriteL(output, pageBytes, 1, fpImage);
    1301                 : 
    1302             711 :             double perc = ((double) (y * maxx + x)) / (maxx * maxy);
    1303                 : //             printf("progress %f\n", perc);
    1304             711 :             if( !pfnProgress( perc, NULL, pProgressData ) )
    1305                 :             {
    1306               0 :                 CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
    1307                 :                 //free(output);
    1308               0 :                 VSIFCloseL( fpImage );
    1309               0 :                 VSIUnlink( pszFilename );
    1310               0 :                 return NULL;
    1311                 :             }
    1312                 :         } // for x
    1313                 : 
    1314                 :     //free(output);
    1315                 : 
    1316              18 :     VSIFCloseL( fpImage );
    1317                 : 
    1318              18 :     pfnProgress( 1.0, NULL, pProgressData );
    1319                 : 
    1320                 : /* -------------------------------------------------------------------- */
    1321                 : /*      Re-open dataset, and copy any auxilary pam information.         */
    1322                 : /* -------------------------------------------------------------------- */
    1323                 :     GDALPamDataset *poDS = (GDALPamDataset *) 
    1324              18 :         GDALOpen( pszFilename, GA_ReadOnly );
    1325                 : 
    1326              18 :     if( poDS )
    1327              18 :         poDS->CloneInfo( poSrcDS, GCIF_PAM_DEFAULT );
    1328                 : 
    1329              18 :     return poDS;
    1330                 : }
    1331                 : #endif // FIT_WRITE
    1332                 : 
    1333                 : /************************************************************************/
    1334                 : /*                           GetGeoTransform()                          */
    1335                 : /************************************************************************/
    1336                 : 
    1337                 : // CPLErr FITDataset::GetGeoTransform( double * padfTransform )
    1338                 : // {
    1339                 : //     CPLDebug("FIT", "FITDataset::GetGeoTransform");
    1340                 : //     memcpy( padfTransform, adfGeoTransform, sizeof(double) * 6 );
    1341                 : //     return( CE_None );
    1342                 : // }
    1343                 : 
    1344                 : /************************************************************************/
    1345                 : /*                          GDALRegister_FIT()                          */
    1346                 : /************************************************************************/
    1347                 : 
    1348             558 : void GDALRegister_FIT()
    1349                 : 
    1350                 : {
    1351                 :     GDALDriver  *poDriver;
    1352                 : 
    1353             558 :     if( GDALGetDriverByName( "FIT" ) == NULL )
    1354                 :     {
    1355             537 :         poDriver = new GDALDriver();
    1356                 :         
    1357             537 :         poDriver->SetDescription( "FIT" );
    1358                 :         poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
    1359             537 :                                    "FIT Image" );
    1360                 :         poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
    1361             537 :                                    "frmt_various.html#" );
    1362             537 :         poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "" );
    1363             537 :         poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
    1364                 : 
    1365             537 :         poDriver->pfnOpen = FITDataset::Open;
    1366                 : #ifdef FIT_WRITE
    1367             537 :         poDriver->pfnCreateCopy = FITCreateCopy;
    1368                 :         poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, 
    1369             537 :                                    "Byte UInt16 Int16 UInt32 Int32 Float32 Float64" );
    1370                 : #endif // FIT_WRITE
    1371                 : 
    1372             537 :         GetGDALDriverManager()->RegisterDriver( poDriver );
    1373                 :     }
    1374             558 : }

Generated by: LCOV version 1.7