LCOV - code coverage report
Current view: directory - frmts/fits - fitsdataset.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 218 178 81.7 %
Date: 2010-01-09 Functions: 13 13 100.0 %

       1                 : /******************************************************************************
       2                 :  * $Id: fitsdataset.cpp 15409 2008-09-22 19:08:15Z rouault $
       3                 :  *
       4                 :  * Project:  FITS Driver
       5                 :  * Purpose:  Implement FITS raster read/write support
       6                 :  * Author:   Simon Perkins, s.perkins@lanl.gov
       7                 :  *
       8                 :  ******************************************************************************
       9                 :  * Copyright (c) 2001, Simon Perkins
      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                 : 
      31                 : 
      32                 : #include "gdal_pam.h"
      33                 : #include "cpl_string.h"
      34                 : #include <string.h>
      35                 : 
      36                 : CPL_CVSID("$Id: fitsdataset.cpp 15409 2008-09-22 19:08:15Z rouault $");
      37                 : 
      38                 : CPL_C_START
      39                 : #include <fitsio.h>
      40                 : void  GDALRegister_FITS(void);
      41                 : CPL_C_END
      42                 : 
      43                 : /************************************************************************/
      44                 : /* ==================================================================== */
      45                 : /*        FITSDataset       */
      46                 : /* ==================================================================== */
      47                 : /************************************************************************/
      48                 : 
      49                 : class FITSRasterBand;
      50                 : 
      51                 : class FITSDataset : public GDALPamDataset {
      52                 : 
      53                 :   friend class FITSRasterBand;
      54                 :   
      55                 :   fitsfile* hFITS;
      56                 : 
      57                 :   GDALDataType gdalDataType;   // GDAL code for the image type
      58                 :   int fitsDataType;   // FITS code for the image type
      59                 : 
      60                 :   bool isExistingFile;
      61                 :   long highestOffsetWritten;  // How much of image has been written
      62                 : 
      63                 :   FITSDataset();     // Others shouldn't call this constructor explicitly
      64                 : 
      65                 :   CPLErr Init(fitsfile* hFITS_, bool isExistingFile_);
      66                 : 
      67                 : public:
      68                 :   ~FITSDataset();
      69                 : 
      70                 :   static GDALDataset* Open(GDALOpenInfo* );
      71                 :   static GDALDataset* Create(const char* pszFilename,
      72                 :            int nXSize, int nYSize, int nBands,
      73                 :            GDALDataType eType,
      74                 :            char** papszParmList);
      75                 :   
      76                 : };
      77                 : 
      78                 : /************************************************************************/
      79                 : /* ==================================================================== */
      80                 : /*                            FITSRasterBand                           */
      81                 : /* ==================================================================== */
      82                 : /************************************************************************/
      83                 : 
      84                 : class FITSRasterBand : public GDALPamRasterBand {
      85                 : 
      86                 :   friend class  FITSDataset;
      87                 :   
      88                 : public:
      89                 : 
      90                 :   FITSRasterBand(FITSDataset*, int);
      91                 :   ~FITSRasterBand();
      92                 : 
      93                 :   virtual CPLErr IReadBlock( int, int, void * );
      94                 :   virtual CPLErr IWriteBlock( int, int, void * ); 
      95                 : };
      96                 : 
      97                 : 
      98                 : /************************************************************************/
      99                 : /*                          FITSRasterBand()                           */
     100                 : /************************************************************************/
     101                 : 
     102              58 : FITSRasterBand::FITSRasterBand(FITSDataset *poDS, int nBand) {
     103                 : 
     104              58 :   this->poDS = poDS;
     105              58 :   this->nBand = nBand;
     106              58 :   eDataType = poDS->gdalDataType;
     107              58 :   nBlockXSize = poDS->nRasterXSize;;
     108              58 :   nBlockYSize = 1;
     109              58 : }
     110                 : 
     111                 : /************************************************************************/
     112                 : /*                          ~FITSRasterBand()                           */
     113                 : /************************************************************************/
     114                 : 
     115             116 : FITSRasterBand::~FITSRasterBand() {
     116              58 :     FlushCache();
     117             116 : }
     118                 : 
     119                 : /************************************************************************/
     120                 : /*                             IReadBlock()                             */
     121                 : /************************************************************************/
     122                 : 
     123             100 : CPLErr FITSRasterBand::IReadBlock(int nBlockXOff, int nBlockYOff,
     124                 :                                   void* pImage ) {
     125                 :  
     126                 :   // A FITS block is one row (we assume BSQ formatted data)
     127             100 :   FITSDataset* dataset = (FITSDataset*) poDS;
     128             100 :   fitsfile* hFITS = dataset->hFITS;
     129             100 :   int status = 0;
     130                 : 
     131                 :   // Since a FITS block is a whole row, nBlockXOff must be zero
     132                 :   // and the row number equals the y block offset. Also, nBlockYOff
     133                 :   // cannot be greater than the number of rows
     134                 :   CPLAssert(nBlockXOff == 0);
     135                 :   CPLAssert(nBlockYOff < nRasterYSize);
     136                 : 
     137                 :   // Calculate offsets and read in the data. Note that FITS array offsets
     138                 :   // start at 1...
     139                 :   long offset = (nBand - 1) * nRasterXSize * nRasterYSize +
     140             100 :     nBlockYOff * nRasterXSize + 1;
     141             100 :   long nElements = nRasterXSize;
     142                 : 
     143                 :   // If we haven't written this block to the file yet, then attempting
     144                 :   // to read causes an error, so in this case, just return zeros.
     145             100 :   if (!dataset->isExistingFile && offset > dataset->highestOffsetWritten) {
     146                 :     memset(pImage, 0, nBlockXSize * nBlockYSize
     147               0 :      * GDALGetDataTypeSize(eDataType) / 8);
     148               0 :     return CE_None;
     149                 :   }
     150                 : 
     151                 :   // Otherwise read in the image data
     152                 :   fits_read_img(hFITS, dataset->fitsDataType, offset, nElements,
     153             100 :     0, pImage, 0, &status);
     154             100 :   if (status) {
     155                 :     CPLError(CE_Failure, CPLE_AppDefined,
     156               0 :        "Couldn't read image data from FITS file (%d).", status);
     157               0 :     return CE_Failure;
     158                 :   }
     159                 :   
     160             100 :   return CE_None;
     161                 : }
     162                 : 
     163                 : /************************************************************************/
     164                 : /*                            IWriteBlock()                             */
     165                 : /*                                                                      */
     166                 : /************************************************************************/
     167                 : 
     168             310 : CPLErr FITSRasterBand::IWriteBlock(int nBlockXOff, int nBlockYOff,
     169                 :            void* pImage) {
     170                 : 
     171             310 :   FITSDataset* dataset = (FITSDataset*) poDS;
     172             310 :   fitsfile* hFITS = dataset->hFITS;
     173             310 :   int status = 0;
     174                 : 
     175                 :   // Since a FITS block is a whole row, nBlockXOff must be zero
     176                 :   // and the row number equals the y block offset. Also, nBlockYOff
     177                 :   // cannot be greater than the number of rows
     178                 : 
     179                 :   // Calculate offsets and read in the data. Note that FITS array offsets
     180                 :   // start at 1...
     181                 :   long offset = (nBand - 1) * nRasterXSize * nRasterYSize +
     182             310 :     nBlockYOff * nRasterXSize + 1;
     183             310 :   long nElements = nRasterXSize;
     184                 :   fits_write_img(hFITS, dataset->fitsDataType, offset, nElements,
     185             310 :      pImage, &status);
     186                 : 
     187                 :   // Capture special case of non-zero status due to data range
     188                 :   // overflow Standard GDAL policy is to silently truncate, which is
     189                 :   // what CFITSIO does, in addition to returning NUM_OVERFLOW (412) as
     190                 :   // the status.
     191             310 :   if (status == NUM_OVERFLOW)
     192               0 :     status = 0;
     193                 : 
     194                 :   // Check for other errors
     195             310 :   if (status) {
     196                 :     CPLError(CE_Failure, CPLE_AppDefined,
     197               0 :        "Error writing image data to FITS file (%d).", status);
     198               0 :     return CE_Failure;
     199                 :   }
     200                 : 
     201                 :   // When we write a block, update the offset counter that we've written
     202             310 :   if (offset > dataset->highestOffsetWritten)
     203             310 :     dataset->highestOffsetWritten = offset;
     204                 : 
     205             310 :   return CE_None;
     206                 : }
     207                 : 
     208                 : /************************************************************************/
     209                 : /* ==================================================================== */
     210                 : /*                             FITSDataset                             */
     211                 : /* ==================================================================== */
     212                 : /************************************************************************/
     213                 : 
     214                 : // Some useful utility functions
     215                 : 
     216                 : // Simple static function to determine if FITS header keyword should
     217                 : // be saved in meta data.
     218                 : static const int ignorableHeaderCount = 15;
     219                 : static const char* ignorableFITSHeaders[ignorableHeaderCount] = {
     220                 :   "SIMPLE", "BITPIX", "NAXIS", "NAXIS1", "NAXIS2", "NAXIS3", "END",
     221                 :   "XTENSION", "PCOUNT", "GCOUNT", "EXTEND", "CONTINUE",
     222                 :   "COMMENT", "", "LONGSTRN"
     223                 : };
     224             399 : static bool isIgnorableFITSHeader(const char* name) {
     225            3148 :   for (int i = 0; i < ignorableHeaderCount; ++i) {
     226            3140 :     if (strcmp(name, ignorableFITSHeaders[i]) == 0)
     227             391 :       return true;
     228                 :   }
     229               8 :   return false;
     230                 : }
     231                 : 
     232                 : 
     233                 : /************************************************************************/
     234                 : /*                            FITSDataset()                            */
     235                 : /************************************************************************/
     236                 : 
     237              39 : FITSDataset::FITSDataset() {
     238              39 :   hFITS = 0;
     239              39 : }
     240                 : 
     241                 : /************************************************************************/
     242                 : /*                           ~FITSDataset()                            */
     243                 : /************************************************************************/
     244                 : 
     245              78 : FITSDataset::~FITSDataset() {
     246                 : 
     247                 :   int status;
     248              39 :   if (hFITS) {
     249              39 :     if(eAccess == GA_Update) {   // Only do this if we've successfully opened the file and  update capability
     250                 :       // Write any meta data to the file that's compatible with FITS
     251              26 :       status = 0;
     252              26 :       fits_movabs_hdu(hFITS, 1, 0, &status);
     253              26 :       fits_write_key_longwarn(hFITS, &status);
     254              26 :       if (status) {
     255                 :         CPLError(CE_Warning, CPLE_AppDefined,
     256                 :            "Couldn't move to first HDU in FITS file %s (%d).\n", 
     257               0 :            GetDescription(), status);
     258                 :       }
     259              26 :       char** metaData = GetMetadata();
     260              26 :       int count = CSLCount(metaData);
     261              42 :       for (int i = 0; i < count; ++i) {
     262              16 :         const char* field = CSLGetField(metaData, i);
     263              16 :         if (strlen(field) == 0)
     264               0 :     continue;
     265                 :         else {
     266                 :     char* key;
     267              16 :     const char* value = CPLParseNameValue(field, &key);
     268                 :     // FITS keys must be less than 8 chars
     269              16 :     if (strlen(key) <= 8 && !isIgnorableFITSHeader(key)) {
     270                 :       // Although FITS provides support for different value
     271                 :       // types, the GDAL Metadata mechanism works only with
     272                 :       // string values. Prior to about 2003-05-02, this driver
     273                 :       // would attempt to guess the value type from the metadata
     274                 :       // value string amd then would use the appropriate
     275                 :       // type-specific FITS keyword update routine. This was
     276                 :       // found to be troublesome (e.g. a numeric version string
     277                 :       // with leading zeros would be interpreted as a number
     278                 :       // and might get those leading zeros stripped), and so now
     279                 :       // the driver writes every value as a string. In practice
     280                 :       // this is not a problem since most FITS reading routines
     281                 :       // will convert from strings to numbers automatically, but
     282                 :       // if you want finer control, use the underlying FITS
     283                 :       // handle. Note: to avoid a compiler warning we copy the
     284                 :       // const value string to a non const one...
     285               2 :       char* valueCpy = strdup(value);
     286               2 :       fits_update_key_longstr(hFITS, key, valueCpy, 0, &status);
     287               2 :       free(valueCpy);
     288                 : 
     289                 :       // Check for errors
     290               2 :       if (status) {
     291                 :         CPLError(CE_Warning, CPLE_AppDefined,
     292                 :            "Couldn't update key %s in FITS file %s (%d).", 
     293               0 :            key, GetDescription(), status);
     294                 :         return;
     295                 :       }
     296                 :     }
     297                 :     // Must free up key
     298              16 :     CPLFree(key);
     299                 :         }
     300                 :       }
     301                 : 
     302                 :       // Make sure we flush the raster cache before we close the file!
     303              26 :       FlushCache();
     304                 :     }
     305                 : 
     306                 :     // Close the FITS handle - ignore the error status
     307              39 :     status = 0;
     308              39 :     fits_close_file(hFITS, &status);
     309                 : 
     310                 :   }
     311              39 : }
     312                 : 
     313                 : 
     314                 : /************************************************************************/
     315                 : /*                           Init()                                     */
     316                 : /************************************************************************/
     317                 : 
     318              39 : CPLErr FITSDataset::Init(fitsfile* hFITS_, bool isExistingFile_) {
     319                 : 
     320              39 :   hFITS = hFITS_;
     321              39 :   isExistingFile = isExistingFile_;
     322              39 :   highestOffsetWritten = 0;
     323              39 :   int status = 0;
     324                 : 
     325                 :   // Move to the primary HDU
     326              39 :   fits_movabs_hdu(hFITS, 1, 0, &status);
     327              39 :   if (status) {
     328                 :     CPLError(CE_Failure, CPLE_AppDefined,
     329                 :        "Couldn't move to first HDU in FITS file %s (%d).\n", 
     330               0 :        GetDescription(), status);
     331               0 :     return CE_Failure;
     332                 :   }
     333                 : 
     334                 :   // The cftsio driver automatically rescales data on read and write
     335                 :   // if BSCALE and BZERO are defined as header keywords. This behavior
     336                 :   // causes overflows with GDAL and is slightly mysterious, so we
     337                 :   // disable this rescaling here.
     338              39 :   fits_set_bscale(hFITS, 1.0, 0.0, &status);
     339                 : 
     340                 :   // Get the image info for this dataset (note that all bands in a FITS dataset
     341                 :   // have the same type)
     342                 :   int bitpix;
     343                 :   int naxis;
     344              39 :   const int maxdim = 3;
     345                 :   long naxes[maxdim];
     346              39 :   fits_get_img_param(hFITS, maxdim, &bitpix, &naxis, naxes, &status);
     347              39 :   if (status) {
     348                 :     CPLError(CE_Failure, CPLE_AppDefined,
     349                 :        "Couldn't determine image parameters of FITS file %s (%d).", 
     350               0 :        GetDescription(), status);
     351               0 :     return CE_Failure;
     352                 :   }
     353                 : 
     354                 :   // Determine data type
     355              39 :   if (bitpix == BYTE_IMG) {
     356              19 :      gdalDataType = GDT_Byte;
     357              19 :      fitsDataType = TBYTE;
     358                 :   }
     359              20 :   else if (bitpix == SHORT_IMG) {
     360               5 :     gdalDataType = GDT_Int16;
     361               5 :     fitsDataType = TSHORT;
     362                 :   }
     363              15 :   else if (bitpix == LONG_IMG) {
     364               5 :     gdalDataType = GDT_Int32;
     365               5 :     fitsDataType = TINT;
     366                 :   }
     367              10 :   else if (bitpix == FLOAT_IMG) {
     368               5 :     gdalDataType = GDT_Float32;
     369               5 :     fitsDataType = TFLOAT;
     370                 :   }
     371               5 :   else if (bitpix == DOUBLE_IMG) {
     372               5 :     gdalDataType = GDT_Float64;
     373               5 :     fitsDataType = TDOUBLE;
     374                 :   }
     375                 :   else {
     376                 :     CPLError(CE_Failure, CPLE_AppDefined,
     377               0 :        "FITS file %s has unknown data type: %d.", GetDescription(), 
     378               0 :        bitpix);
     379               0 :     return CE_Failure;
     380                 :   }
     381                 : 
     382                 :   // Determine image dimensions - we assume BSQ ordering
     383              39 :   if (naxis == 2) {
     384              30 :     nRasterXSize = naxes[0];
     385              30 :     nRasterYSize = naxes[1];
     386              30 :     nBands = 1;
     387                 :   }
     388               9 :   else if (naxis == 3) {
     389               9 :     nRasterXSize = naxes[0];
     390               9 :     nRasterYSize = naxes[1];
     391               9 :     nBands = naxes[2];
     392                 :   }
     393                 :   else {
     394                 :     CPLError(CE_Failure, CPLE_AppDefined,
     395                 :        "FITS file %s does not have 2 or 3 dimensions.", 
     396               0 :        GetDescription());
     397               0 :     return CE_Failure;
     398                 :   }
     399                 :   
     400                 :   // Create the bands
     401             194 :   for (int i = 0; i < nBands; ++i)
     402              58 :     SetBand(i+1, new FITSRasterBand(this, i+1));
     403                 : 
     404                 :   // Read header information from file and use it to set metadata
     405                 :   // This process understands the CONTINUE standard for long strings.
     406                 :   // We don't bother to capture header names that duplicate information
     407                 :   // already captured elsewhere (e.g. image dimensions and type)
     408              39 :   int keyNum = 1;
     409                 :   char key[100];
     410                 :   char value[100];
     411              39 :   bool endReached = false;
     412             436 :   do {
     413             436 :     fits_read_keyn(hFITS, keyNum, key, value, 0, &status);
     414             436 :     if (status) {
     415                 :       CPLError(CE_Failure, CPLE_AppDefined,
     416                 :          "Error while reading key %d from FITS file %s (%d)", 
     417               0 :          keyNum, GetDescription(), status);
     418               0 :       return CE_Failure;
     419                 :     }
     420                 :     // What we do next depends upon the key and the value
     421             436 :     if (strcmp(key, "END") == 0) {
     422              39 :       endReached = true;
     423                 :     }
     424             397 :     else if (isIgnorableFITSHeader(key)) {
     425                 :       // Ignore it!
     426                 :     }
     427                 :     else {   // Going to store something, but check for long strings etc
     428                 :       // Strip off leading and trailing quote if present
     429               6 :       char* newValue = value;
     430               6 :       if (value[0] == '\'' && value[strlen(value) - 1] == '\'') {
     431               6 :   newValue = value + 1;
     432               6 :   value[strlen(value) - 1] = '\0';
     433                 :       }
     434                 :       // Check for long string
     435               6 :       if (strrchr(newValue, '&') == newValue + strlen(newValue) - 1) {
     436                 :   // Value string ends in "&", so use long string conventions
     437               0 :   char* longString = 0;
     438               0 :   fits_read_key_longstr(hFITS, key, &longString, 0, &status);
     439                 :   // Note that read_key_longst already strips quotes
     440               0 :   if (status) {
     441                 :     CPLError(CE_Failure, CPLE_AppDefined,
     442                 :        "Error while reading long string for key %s from "
     443               0 :        "FITS file %s (%d)", key, GetDescription(), status);
     444               0 :     return CE_Failure;
     445                 :   }
     446               0 :   SetMetadataItem(key, longString);
     447               0 :   free(longString);
     448                 :       }
     449                 :       else {  // Normal keyword
     450               6 :   SetMetadataItem(key, newValue);
     451                 :       }
     452                 :     }
     453             436 :     ++keyNum;
     454                 :   } while (!endReached);
     455                 :   
     456              39 :   return CE_None;
     457                 : }
     458                 : 
     459                 : 
     460                 : 
     461                 : /************************************************************************/
     462                 : /*                                Open()                                */
     463                 : /************************************************************************/
     464                 : 
     465            9643 : GDALDataset* FITSDataset::Open(GDALOpenInfo* poOpenInfo) {
     466                 : 
     467            9643 :   const char* fitsID = "SIMPLE  =                    T";  // Spaces important!
     468            9643 :   size_t fitsIDLen = strlen(fitsID);  // Should be 30 chars long
     469                 : 
     470            9643 :   if ((size_t)poOpenInfo->nHeaderBytes < fitsIDLen)
     471            8661 :     return NULL;
     472             982 :   if (memcmp(poOpenInfo->pabyHeader, fitsID, fitsIDLen))
     473             968 :     return NULL;
     474                 :   
     475                 :   // Get access mode and attempt to open the file
     476              14 :   int status = 0;
     477              14 :   fitsfile* hFITS = 0;
     478              14 :   if (poOpenInfo->eAccess == GA_ReadOnly) 
     479              13 :     fits_open_file(&hFITS, poOpenInfo->pszFilename, READONLY, &status);
     480                 :   else
     481               1 :     fits_open_file(&hFITS, poOpenInfo->pszFilename, READWRITE, &status);
     482              14 :   if (status) {
     483                 :     CPLError(CE_Failure, CPLE_AppDefined,
     484                 :        "Error while opening FITS file %s (%d).\n", 
     485               0 :        poOpenInfo->pszFilename, status);
     486               0 :     fits_close_file(hFITS, &status);
     487               0 :     return NULL;
     488                 :   }
     489                 : 
     490                 :   // Create a FITSDataset object and initialize it from the FITS handle
     491              14 :   FITSDataset* dataset = new FITSDataset();
     492              14 :   dataset->eAccess = poOpenInfo->eAccess;
     493                 : 
     494                 :   // Set up the description and initialize the dataset
     495              14 :   dataset->SetDescription(poOpenInfo->pszFilename);
     496              14 :   if (dataset->Init(hFITS, true) != CE_None) {
     497               0 :     delete dataset;
     498               0 :     return NULL;
     499                 :   }
     500                 :   else
     501                 :   {
     502                 : /* -------------------------------------------------------------------- */
     503                 : /*      Initialize any PAM information.                                 */
     504                 : /* -------------------------------------------------------------------- */
     505              14 :       dataset->SetDescription( poOpenInfo->pszFilename );
     506              14 :       dataset->TryLoadXML();
     507                 : 
     508              14 :       return dataset;
     509                 :   }
     510                 : }
     511                 : 
     512                 : 
     513                 : /************************************************************************/
     514                 : /*                               Create()                               */
     515                 : /*                                                                      */
     516                 : /*      Create a new FITS file.                                         */
     517                 : /************************************************************************/
     518                 : 
     519              37 : GDALDataset *FITSDataset::Create(const char* pszFilename,
     520                 :          int nXSize, int nYSize, 
     521                 :          int nBands, GDALDataType eType,
     522                 :          char** papszParmList) {
     523                 : 
     524                 : 
     525                 :   FITSDataset* dataset;
     526                 :   fitsfile* hFITS;
     527              37 :   int status = 0;
     528                 : 
     529                 :   // No creation options are defined. The BSCALE/BZERO options were
     530                 :   // removed on 2002-07-02 by Simon Perkins because they introduced
     531                 :   // excessive complications and didn't really fit into the GDAL
     532                 :   // paradigm.
     533                 : 
     534                 :   // Create the file - to force creation, we prepend the name with '!'
     535              37 :   char* extFilename = new char[strlen(pszFilename) + 10];  // 10 for margin!
     536              37 :   sprintf(extFilename, "!%s", pszFilename);
     537              37 :   fits_create_file(&hFITS, extFilename, &status);
     538              37 :   delete[] extFilename;
     539              37 :   if (status) {
     540                 :     CPLError(CE_Failure, CPLE_AppDefined,
     541               0 :        "Couldn't create FITS file %s (%d).\n", pszFilename, status);
     542               0 :     return NULL;
     543                 :   }
     544                 : 
     545                 :   // Determine FITS type of image
     546                 :   int bitpix;
     547              37 :   if (eType == GDT_Byte)
     548              13 :     bitpix = BYTE_IMG;
     549              24 :   else if (eType == GDT_Int16)
     550               3 :     bitpix = SHORT_IMG;
     551              21 :   else if (eType == GDT_Int32)
     552               3 :     bitpix = LONG_IMG;
     553              18 :   else if (eType == GDT_Float32)
     554               3 :     bitpix = FLOAT_IMG;
     555              15 :   else if (eType == GDT_Float64)
     556               3 :     bitpix = DOUBLE_IMG;
     557                 :   else {
     558                 :     CPLError(CE_Failure, CPLE_AppDefined,
     559              12 :        "GDALDataType (%d) unsupported for FITS", eType);
     560              12 :     fits_close_file(hFITS, &status);
     561              12 :     return NULL;
     562                 :   }
     563                 : 
     564                 :   // Now create an image of appropriate size and type
     565              25 :   long naxes[3] = {nXSize, nYSize, nBands};
     566              25 :   int naxis = (nBands == 1) ? 2 : 3;
     567              25 :   fits_create_img(hFITS, bitpix, naxis, naxes, &status);
     568                 : 
     569                 :   // Check the status
     570              25 :   if (status) {
     571                 :     CPLError(CE_Failure, CPLE_AppDefined,
     572                 :        "Couldn't create image within FITS file %s (%d).", 
     573               0 :        pszFilename, status);
     574               0 :     fits_close_file(hFITS, &status);
     575               0 :     return NULL;
     576                 :   }
     577                 : 
     578              25 :   dataset = new FITSDataset();
     579              25 :   dataset->nRasterXSize = nXSize;
     580              25 :   dataset->nRasterYSize = nYSize;
     581              25 :   dataset->eAccess = GA_Update;
     582              25 :   dataset->SetDescription(pszFilename);
     583                 : 
     584                 :   // Init recalculates a lot of stuff we already know, but...
     585              25 :   if (dataset->Init(hFITS, false) != CE_None) { 
     586               0 :     delete dataset;
     587               0 :     return NULL;
     588                 :   }
     589                 :   else {
     590              25 :     return dataset;
     591                 :   }
     592                 : }
     593                 : 
     594                 : 
     595                 : /************************************************************************/
     596                 : /*                          GDALRegister_FITS()                        */
     597                 : /************************************************************************/
     598                 : 
     599             338 : void GDALRegister_FITS() {
     600                 : 
     601                 :     GDALDriver* poDriver;
     602                 : 
     603             338 :     if( GDALGetDriverByName( "FITS" ) == NULL) {
     604             336 :         poDriver = new GDALDriver();
     605                 :         
     606             336 :         poDriver->SetDescription( "FITS" );
     607                 :         poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
     608             336 :                                    "Flexible Image Transport System" );
     609                 :         poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
     610             336 :                                    "frmt_various.html#FITS" );
     611                 :         poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, 
     612             336 :                                    "Byte Int16 Int32 Float32 Float64" );
     613                 :         
     614             336 :         poDriver->pfnOpen = FITSDataset::Open;
     615             336 :         poDriver->pfnCreate = FITSDataset::Create;
     616             336 :         poDriver->pfnCreateCopy = NULL;
     617                 : 
     618             336 :         GetGDALDriverManager()->RegisterDriver(poDriver);
     619                 :     }
     620             338 : }

Generated by: LCOV version 1.7