LCOV - code coverage report
Current view: directory - frmts/sgi - sgidataset.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 319 265 83.1 %
Date: 2012-04-28 Functions: 21 16 76.2 %

       1                 : /******************************************************************************
       2                 :  * $Id: sgidataset.cpp 21680 2011-02-11 21:12:07Z warmerdam $
       3                 :  *
       4                 :  * Project:  SGI Image Driver
       5                 :  * Purpose:  Implement SGI Image Support based on Paul Bourke's SGI Image code.
       6                 :  *           http://astronomy.swin.edu.au/~pbourke/dataformats/sgirgb/
       7                 :  *           ftp://ftp.sgi.com/graphics/SGIIMAGESPEC
       8                 :  * Authors:  Mike Mazzella (GDAL driver)
       9                 :  *           Paul Bourke (original SGI format code)
      10                 :  *           Frank Warmerdam (write support)
      11                 :  *
      12                 :  ******************************************************************************
      13                 :  * Copyright (c) 2005, Frank Warmerdam <warmerdam@pobox.com>
      14                 :  *
      15                 :  * Permission is hereby granted, free of charge, to any person obtaining a
      16                 :  * copy of this software and associated documentation files (the "Software"),
      17                 :  * to deal in the Software without restriction, including without limitation
      18                 :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      19                 :  * and/or sell copies of the Software, and to permit persons to whom the
      20                 :  * Software is furnished to do so, subject to the following conditions:
      21                 :  *
      22                 :  * The above copyright notice and this permission notice shall be included
      23                 :  * in all copies or substantial portions of the Software.
      24                 :  *
      25                 :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      26                 :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      27                 :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      28                 :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      29                 :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      30                 :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      31                 :  * DEALINGS IN THE SOFTWARE.
      32                 :  ****************************************************************************/
      33                 : 
      34                 : #include "gdal_pam.h"
      35                 : #include "cpl_port.h"
      36                 : #include "cpl_string.h"
      37                 : 
      38                 : CPL_CVSID("$Id: sgidataset.cpp 21680 2011-02-11 21:12:07Z warmerdam $");
      39                 : 
      40                 : CPL_C_START
      41                 : void  GDALRegister_SGI(void);
      42                 : CPL_C_END
      43                 : 
      44                 : struct ImageRec
      45            3316 : {
      46                 :     GUInt16 imagic;
      47                 :     GByte type;
      48                 :     GByte bpc;
      49                 :     GUInt16 dim;
      50                 :     GUInt16 xsize;
      51                 :     GUInt16 ysize;
      52                 :     GUInt16 zsize;
      53                 :     GUInt32 min;
      54                 :     GUInt32 max;
      55                 :     char wasteBytes[4];
      56                 :     char name[80];
      57                 :     GUInt32 colorMap;
      58                 : 
      59                 :     VSILFILE* file;
      60                 :     std::string fileName;
      61                 :     unsigned char* tmp;
      62                 :     GUInt32 rleEnd;
      63                 :     int     rleTableDirty;
      64                 :     GUInt32* rowStart;
      65                 :     GInt32* rowSize;
      66                 : 
      67            3316 :     ImageRec()
      68                 :             : imagic(0),
      69                 :               type(0),
      70                 :               bpc(1),
      71                 :               dim(0),
      72                 :               xsize(0),
      73                 :               ysize(0),
      74                 :               zsize(0),
      75                 :               min(0),
      76                 :               max(0),
      77                 :               colorMap(0),
      78                 :               file(NULL),
      79                 :               fileName(""),
      80                 :               tmp(NULL),
      81                 :               rleEnd(0),
      82                 :               rleTableDirty(FALSE),
      83                 :               rowStart(NULL),
      84            3316 :               rowSize(NULL)
      85                 :         {
      86            3316 :             memset(wasteBytes, 0, 4);
      87            3316 :             memset(name, 0, 80);
      88            3316 :         }
      89                 : 
      90            3316 :     void Swap()
      91                 :         {
      92                 : #ifdef CPL_LSB
      93            3316 :             CPL_SWAP16PTR(&imagic);
      94            3316 :             CPL_SWAP16PTR(&dim);
      95            3316 :             CPL_SWAP16PTR(&xsize);
      96            3316 :             CPL_SWAP16PTR(&ysize);
      97            3316 :             CPL_SWAP16PTR(&zsize);
      98            3316 :             CPL_SWAP32PTR(&min);
      99            3316 :             CPL_SWAP32PTR(&max);
     100                 : #endif
     101            3316 :         }
     102                 : };
     103                 : 
     104                 : /************************************************************************/
     105                 : /*                            ConvertLong()                             */
     106                 : /************************************************************************/
     107             116 : static void ConvertLong(GUInt32* array, GInt32 length) 
     108                 : {
     109                 : #ifdef CPL_LSB
     110                 :    GUInt32* ptr;
     111             116 :    ptr = (GUInt32*)array;
     112           14632 :    while(length--)
     113           14400 :      CPL_SWAP32PTR(ptr++);
     114                 : #endif
     115             116 : }
     116                 : 
     117                 : /************************************************************************/
     118                 : /*                            ImageGetRow()                             */
     119                 : /************************************************************************/
     120             180 : static CPLErr ImageGetRow(ImageRec* image, unsigned char* buf, int y, int z) 
     121                 : {
     122                 :     unsigned char *iPtr, *oPtr, pixel;
     123                 :     int count;
     124                 : 
     125             180 :     y = image->ysize - 1 - y;
     126                 : 
     127             180 :     if(int(image->type) == 1)
     128                 :     {
     129                 :         // reads row
     130             180 :         VSIFSeekL(image->file, (long)image->rowStart[y+z*image->ysize], SEEK_SET);
     131             180 :         if(VSIFReadL(image->tmp, 1, (GUInt32)image->rowSize[y+z*image->ysize], image->file) != (GUInt32)image->rowSize[y+z*image->ysize])
     132                 :         {
     133               0 :             CPLError(CE_Failure, CPLE_OpenFailed, "file read error: row (%d) of (%s)\n", y, image->fileName.empty() ? "none" : image->fileName.c_str());
     134               0 :             return CE_Failure;
     135                 :         }
     136                 : 
     137                 :         // expands row
     138             180 :         iPtr = image->tmp;
     139             180 :         oPtr = buf;
     140             180 :         int xsizeCount = 0;
     141             396 :         for(;;)
     142                 :         {
     143             576 :             pixel = *iPtr++;
     144             576 :             count = (int)(pixel & 0x7F);
     145             576 :             if(!count)
     146                 :             {
     147             180 :                 if(xsizeCount != image->xsize)
     148                 :                 {
     149               0 :                     CPLError(CE_Failure, CPLE_OpenFailed, "file read error: row (%d) of (%s)\n", y, image->fileName.empty() ? "none" : image->fileName.c_str());
     150               0 :                     return CE_Failure;
     151                 :                 }
     152                 :                 else
     153                 :                 {
     154             180 :                     return CE_None;
     155                 :                 }
     156                 :             }
     157                 : 
     158             396 :             if( xsizeCount + count > image->xsize )
     159                 :             {
     160               0 :                 CPLError(CE_Failure, CPLE_AppDefined, "Wrong repetition number that would overflow data at line %d", y);
     161               0 :                 return CE_Failure;
     162                 :             }
     163                 : 
     164             396 :             if(pixel & 0x80)
     165                 :             {
     166             220 :         memcpy(oPtr, iPtr, count);
     167             220 :         iPtr += count;
     168                 :             }
     169                 :             else
     170                 :             {
     171             176 :                 pixel = *iPtr++;
     172             176 :     memset(oPtr, pixel, count);
     173                 :             }
     174             396 :       oPtr += count;
     175             396 :       xsizeCount += count;
     176                 :         }
     177                 :     }
     178                 :     else
     179                 :     {
     180               0 :         VSIFSeekL(image->file, 512+(y*image->xsize)+(z*image->xsize*image->ysize), SEEK_SET);
     181               0 :         if(VSIFReadL(buf, 1, image->xsize, image->file) != image->xsize)
     182                 :         {
     183               0 :             CPLError(CE_Failure, CPLE_OpenFailed, "file read error: row (%d) of (%s)\n", y, image->fileName.empty() ? "none" : image->fileName.c_str());
     184               0 :             return CE_Failure;
     185                 :         }
     186                 :     }
     187                 : 
     188               0 :     return CE_None;
     189                 : }
     190                 : 
     191                 : /************************************************************************/
     192                 : /* ==================================================================== */
     193                 : /*        SGIDataset        */
     194                 : /* ==================================================================== */
     195                 : /************************************************************************/
     196                 : 
     197                 : class SGIRasterBand;
     198                 : 
     199                 : class SGIDataset : public GDALPamDataset
     200                 : {
     201                 :     friend class SGIRasterBand;
     202                 : 
     203                 :     VSILFILE*  fpImage;
     204                 : 
     205                 :     int    bGeoTransformValid;
     206                 :     double adfGeoTransform[6];
     207                 : 
     208                 :     ImageRec image;
     209                 : 
     210                 : public:
     211                 :     SGIDataset();
     212                 :     ~SGIDataset();
     213                 : 
     214                 :     virtual CPLErr GetGeoTransform(double*);
     215                 :     static GDALDataset* Open(GDALOpenInfo*);
     216                 :     static GDALDataset *Create( const char * pszFilename,
     217                 :                                 int nXSize, int nYSize, int nBands,
     218                 :                                 GDALDataType eType, char **papszOptions );
     219                 : };
     220                 : 
     221                 : /************************************************************************/
     222                 : /* ==================================================================== */
     223                 : /*                            SGIRasterBand                             */
     224                 : /* ==================================================================== */
     225                 : /************************************************************************/
     226                 : 
     227                 : class SGIRasterBand : public GDALPamRasterBand
     228             104 : {
     229                 :     friend class SGIDataset;
     230                 : 
     231                 : public:
     232                 :     SGIRasterBand(SGIDataset*, int);
     233                 : 
     234                 :     virtual CPLErr IReadBlock(int, int, void*);
     235                 :     virtual CPLErr IWriteBlock(int, int, void*);
     236                 :     virtual GDALColorInterp GetColorInterpretation();
     237                 : };
     238                 : 
     239                 : 
     240                 : /************************************************************************/
     241                 : /*                           SGIRasterBand()                            */
     242                 : /************************************************************************/
     243                 : 
     244             104 : SGIRasterBand::SGIRasterBand(SGIDataset* poDS, int nBand)
     245                 : 
     246                 : {
     247             104 :   this->poDS = poDS;
     248             104 :   this->nBand = nBand;
     249             104 :   if(poDS == NULL)
     250                 :   {
     251               0 :     eDataType = GDT_Byte;
     252                 :   }
     253                 :   else
     254                 :   {
     255             104 :     if(int(poDS->image.bpc) == 1)
     256             104 :       eDataType = GDT_Byte;
     257                 :     else
     258               0 :       eDataType = GDT_Int16;
     259                 :   }
     260             104 :   nBlockXSize = poDS->nRasterXSize;;
     261             104 :   nBlockYSize = 1;
     262             104 : }
     263                 : 
     264                 : /************************************************************************/
     265                 : /*                             IReadBlock()                             */
     266                 : /************************************************************************/
     267                 : 
     268             180 : CPLErr SGIRasterBand::IReadBlock(int nBlockXOff, int nBlockYOff,
     269                 :          void*  pImage)
     270                 : 
     271                 : {
     272             180 :     SGIDataset* poGDS = (SGIDataset*) poDS;
     273                 :     
     274             180 :     CPLAssert(nBlockXOff == 0);
     275                 : 
     276                 : /* -------------------------------------------------------------------- */
     277                 : /*      Load the desired data into the working buffer.              */
     278                 : /* -------------------------------------------------------------------- */
     279             180 :     return ImageGetRow(&(poGDS->image), (unsigned char*)pImage, nBlockYOff, nBand-1);
     280                 : }
     281                 : 
     282                 : /************************************************************************/
     283                 : /*                             IWritelock()                             */
     284                 : /************************************************************************/
     285                 : 
     286             440 : CPLErr SGIRasterBand::IWriteBlock(int nBlockXOff, int nBlockYOff,
     287                 :                                   void*  pImage)
     288                 : 
     289                 : {
     290             440 :     SGIDataset* poGDS = (SGIDataset*) poDS;
     291             440 :     ImageRec *image = &(poGDS->image);
     292                 :     
     293             440 :     CPLAssert(nBlockXOff == 0);
     294                 : 
     295                 : /* -------------------------------------------------------------------- */
     296                 : /*      Handle the fairly trivial non-RLE case.                         */
     297                 : /* -------------------------------------------------------------------- */
     298             440 :     if( image->type == 0 )
     299                 :     {
     300                 :         VSIFSeekL(image->file, 
     301                 :                   512 + (nBlockYOff*image->xsize)
     302                 :                   + ((nBand-1)*image->xsize*image->ysize ), 
     303               0 :                   SEEK_SET);
     304               0 :         if(VSIFWriteL(pImage, 1, image->xsize, image->file) != image->xsize)
     305                 :         {
     306                 :             CPLError(CE_Failure, CPLE_OpenFailed, 
     307               0 :                      "file write error: row (%d)\n", nBlockYOff );
     308               0 :             return CE_Failure;
     309                 :         }
     310               0 :         return CE_None;
     311                 :     }
     312                 : 
     313                 : /* -------------------------------------------------------------------- */
     314                 : /*      Handle RLE case.                                                */
     315                 : /* -------------------------------------------------------------------- */
     316             440 :     const GByte *pabyRawBuf = (const GByte *) pImage;
     317             440 :     GByte *pabyRLEBuf = (GByte *) CPLMalloc(image->xsize * 2 + 6);
     318             440 :     int iX = 0, nRLEBytes = 0;
     319                 : 
     320            1496 :     while( iX < image->xsize )
     321                 :     {
     322             616 :         int nRepeatCount = 1;
     323                 : 
     324           13308 :         while( iX + nRepeatCount < image->xsize
     325                 :                && nRepeatCount < 127
     326            8260 :                && pabyRawBuf[iX + nRepeatCount] == pabyRawBuf[iX] )
     327            3816 :             nRepeatCount++;
     328                 : 
     329            1484 :         if( nRepeatCount > 2 
     330                 :             || iX + nRepeatCount == image->xsize
     331                 :             || (iX + nRepeatCount < image->xsize - 2
     332             176 :                 && pabyRawBuf[iX + nRepeatCount + 1] 
     333             176 :                 == pabyRawBuf[iX + nRepeatCount + 2]
     334              32 :                 && pabyRawBuf[iX + nRepeatCount + 1] 
     335              32 :                 == pabyRawBuf[iX + nRepeatCount + 3]) )
     336                 :         { // encode a constant run.
     337             452 :             pabyRLEBuf[nRLEBytes++] = (GByte) nRepeatCount; 
     338             452 :             pabyRLEBuf[nRLEBytes++] = pabyRawBuf[iX];
     339             452 :             iX += nRepeatCount;
     340                 :         }
     341                 :         else 
     342                 :         { // copy over mixed data. 
     343             164 :             nRepeatCount = 1;
     344                 : 
     345            4544 :             for( nRepeatCount = 1;
     346                 :                  iX + nRepeatCount < image->xsize && nRepeatCount < 127;
     347                 :                  nRepeatCount++ )
     348                 :             {
     349            4406 :                 if( iX + nRepeatCount + 3 >= image->xsize )
     350             408 :                     continue;
     351                 : 
     352                 :                 // quit if the next 3 pixels match
     353            8360 :                 if( pabyRawBuf[iX + nRepeatCount] 
     354            3998 :                     == pabyRawBuf[iX + nRepeatCount+1] 
     355             182 :                     && pabyRawBuf[iX + nRepeatCount] 
     356             182 :                     == pabyRawBuf[iX + nRepeatCount+2] )
     357              26 :                     break;
     358                 :             }
     359                 : 
     360             164 :             pabyRLEBuf[nRLEBytes++] = (GByte) (0x80 | nRepeatCount); 
     361                 :             memcpy( pabyRLEBuf + nRLEBytes, 
     362                 :                     pabyRawBuf + iX, 
     363             164 :                     nRepeatCount );
     364                 :             
     365             164 :             nRLEBytes += nRepeatCount;
     366             164 :             iX += nRepeatCount;
     367                 :         }
     368                 :     }
     369                 : 
     370                 :     // EOL marker.
     371             440 :     pabyRLEBuf[nRLEBytes++] = 0;
     372                 : 
     373                 : /* -------------------------------------------------------------------- */
     374                 : /*      Write RLE Buffer at end of file.                                */
     375                 : /* -------------------------------------------------------------------- */
     376             440 :     int row = (image->ysize - nBlockYOff - 1) + (nBand-1) * image->ysize;
     377                 : 
     378             440 :     VSIFSeekL(image->file, 0, SEEK_END );
     379                 : 
     380             440 :     image->rowStart[row] = (GUInt32) VSIFTellL( image->file );
     381             440 :     image->rowSize[row] = nRLEBytes;
     382             440 :     image->rleTableDirty = TRUE;
     383                 : 
     384             440 :     if( (int) VSIFWriteL(pabyRLEBuf, 1, nRLEBytes, image->file) != nRLEBytes )
     385                 :     {
     386               0 :         CPLFree( pabyRLEBuf );
     387                 :         CPLError(CE_Failure, CPLE_OpenFailed, 
     388               0 :                  "file write error: row (%d)\n", nBlockYOff );
     389               0 :         return CE_Failure;
     390                 :     }
     391                 : 
     392             440 :     CPLFree( pabyRLEBuf );
     393                 : 
     394             440 :     return CE_None;
     395                 : }
     396                 : 
     397                 : /************************************************************************/
     398                 : /*                       GetColorInterpretation()                       */
     399                 : /************************************************************************/
     400                 : 
     401              20 : GDALColorInterp SGIRasterBand::GetColorInterpretation()
     402                 : 
     403                 : {
     404              20 :     SGIDataset* poGDS = (SGIDataset*)poDS;
     405                 : 
     406              20 :     if(poGDS->nBands == 1)
     407               2 :         return GCI_GrayIndex;
     408              18 :     else if(poGDS->nBands == 2)
     409                 :     {
     410               2 :         if(nBand == 1)
     411               2 :             return GCI_GrayIndex;
     412                 :         else
     413               0 :             return GCI_AlphaBand;
     414                 :     }
     415              16 :     else if(poGDS->nBands == 3)
     416                 :     {
     417               6 :         if(nBand == 1)
     418               2 :             return GCI_RedBand;
     419               4 :         else if(nBand == 2)
     420               2 :             return GCI_GreenBand;
     421                 :         else
     422               2 :             return GCI_BlueBand;
     423                 :     }
     424              10 :     else if(poGDS->nBands == 4)
     425                 :     {
     426               8 :         if(nBand == 1)
     427               2 :             return GCI_RedBand;
     428               6 :         else if(nBand == 2)
     429               2 :             return GCI_GreenBand;
     430               4 :         else if(nBand == 3)
     431               2 :             return GCI_BlueBand;
     432                 :         else
     433               2 :             return GCI_AlphaBand;
     434                 :     }
     435               2 :     return GCI_Undefined;
     436                 : }
     437                 : 
     438                 : /************************************************************************/
     439                 : /* ==================================================================== */
     440                 : /*                             SGIDataset                               */
     441                 : /* ==================================================================== */
     442                 : /************************************************************************/
     443                 : 
     444                 : 
     445                 : /************************************************************************/
     446                 : /*                            SGIDataset()                              */
     447                 : /************************************************************************/
     448                 : 
     449              48 : SGIDataset::SGIDataset()
     450                 :   : fpImage(NULL),
     451              48 :     bGeoTransformValid(FALSE)
     452                 : {
     453              48 :     adfGeoTransform[0] = 0.0;
     454              48 :     adfGeoTransform[1] = 1.0;
     455              48 :     adfGeoTransform[2] = 0.0;
     456              48 :     adfGeoTransform[3] = 0.0;
     457              48 :     adfGeoTransform[4] = 0.0;
     458              48 :     adfGeoTransform[5] = 1.0;
     459              48 : }
     460                 : 
     461                 : /************************************************************************/
     462                 : /*                           ~SGIDataset()                            */
     463                 : /************************************************************************/
     464                 : 
     465              48 : SGIDataset::~SGIDataset()
     466                 : 
     467                 : {
     468              48 :     FlushCache();
     469                 : 
     470                 :     // Do we need to write out rle table?
     471              48 :     if( image.rleTableDirty )
     472                 :     {
     473              14 :         CPLDebug( "SGI", "Flushing RLE offset table." );
     474              14 :         ConvertLong( image.rowStart, image.ysize * image.zsize );
     475              14 :         ConvertLong( (GUInt32 *) image.rowSize, image.ysize * image.zsize );
     476                 : 
     477              14 :         VSIFSeekL( fpImage, 512, SEEK_SET );
     478              14 :         VSIFWriteL( image.rowStart, 4, image.ysize * image.zsize, fpImage );
     479              14 :         VSIFWriteL( image.rowSize, 4, image.ysize * image.zsize, fpImage );
     480              14 :         image.rleTableDirty = FALSE;
     481                 :     }
     482                 : 
     483              48 :     if(fpImage != NULL)
     484              48 :         VSIFCloseL(fpImage);
     485                 : 
     486              48 :     CPLFree(image.tmp);
     487              48 :     CPLFree(image.rowSize);
     488              48 :     CPLFree(image.rowStart);
     489              48 : }
     490                 : 
     491                 : /************************************************************************/
     492                 : /*                          GetGeoTransform()                           */
     493                 : /************************************************************************/
     494                 : 
     495              10 : CPLErr SGIDataset::GetGeoTransform(double * padfTransform)
     496                 : 
     497                 : {
     498              10 :     if(bGeoTransformValid)
     499                 :     {
     500               0 :         memcpy(padfTransform, adfGeoTransform, sizeof(double)*6);
     501                 :         
     502               0 :         return CE_None;
     503                 :     }
     504                 :     else 
     505              10 :         return GDALPamDataset::GetGeoTransform(padfTransform);
     506                 : }
     507                 : 
     508                 : /************************************************************************/
     509                 : /*                                Open()                                */
     510                 : /************************************************************************/
     511                 : 
     512           25572 : GDALDataset* SGIDataset::Open(GDALOpenInfo* poOpenInfo)
     513                 : 
     514                 : {
     515                 : /* -------------------------------------------------------------------- */
     516                 : /*  First we check to see if the file has the expected header */
     517                 : /*  bytes.                */    
     518                 : /* -------------------------------------------------------------------- */
     519           25572 :     if(poOpenInfo->nHeaderBytes < 12)
     520           22304 :         return NULL;
     521                 : 
     522            3268 :     ImageRec tmpImage;
     523            3268 :     memcpy(&tmpImage, poOpenInfo->pabyHeader, 12);
     524            3268 :     tmpImage.Swap();
     525                 : 
     526            3268 :     if(tmpImage.imagic != 474)
     527            3220 :         return NULL;
     528                 : 
     529              48 :     if (tmpImage.type != 0 && tmpImage.type != 1)
     530               0 :         return NULL;
     531                 : 
     532              48 :     if (tmpImage.bpc != 1 && tmpImage.bpc != 2)
     533               0 :         return NULL;
     534                 : 
     535              48 :     if (tmpImage.dim != 1 && tmpImage.dim != 2 && tmpImage.dim != 3)
     536               0 :         return NULL;
     537                 : 
     538              48 :     if(tmpImage.bpc != 1)
     539                 :     {
     540                 :         CPLError(CE_Failure, CPLE_NotSupported, 
     541               0 :                  "The SGI driver only supports 1 byte channel values.\n");
     542               0 :         return NULL;
     543                 :     }
     544                 :   
     545                 : /* -------------------------------------------------------------------- */
     546                 : /*      Create a corresponding GDALDataset.                             */
     547                 : /* -------------------------------------------------------------------- */
     548                 :     SGIDataset* poDS;
     549                 : 
     550              48 :     poDS = new SGIDataset();
     551              48 :     poDS->eAccess = poOpenInfo->eAccess;
     552                 : 
     553                 : /* -------------------------------------------------------------------- */
     554                 : /*      Open the file using the large file api.                         */
     555                 : /* -------------------------------------------------------------------- */
     556              48 :     if( poDS->eAccess == GA_ReadOnly )
     557              22 :         poDS->fpImage = VSIFOpenL(poOpenInfo->pszFilename, "rb");
     558                 :     else
     559              26 :         poDS->fpImage = VSIFOpenL(poOpenInfo->pszFilename, "rb+");
     560              48 :     if(poDS->fpImage == NULL)
     561                 :     {
     562                 :         CPLError(CE_Failure, CPLE_OpenFailed, 
     563                 :                  "VSIFOpenL(%s) failed unexpectedly in sgidataset.cpp\n%s", 
     564                 :                  poOpenInfo->pszFilename,
     565               0 :                  VSIStrerror( errno ) );
     566               0 :         delete poDS;
     567               0 :         return NULL;
     568                 :     }
     569                 : 
     570                 : /* -------------------------------------------------------------------- */
     571                 : /*  Read pre-image data after ensuring the file is rewound.         */
     572                 : /* -------------------------------------------------------------------- */
     573              48 :     VSIFSeekL(poDS->fpImage, 0, SEEK_SET);
     574              48 :     if(VSIFReadL((void*)(&(poDS->image)), 1, 12, poDS->fpImage) != 12)
     575                 :     {
     576               0 :         CPLError(CE_Failure, CPLE_OpenFailed, "file read error while reading header in sgidataset.cpp");
     577               0 :         delete poDS;
     578               0 :         return NULL;
     579                 :     }
     580              48 :     poDS->image.Swap();
     581              48 :     poDS->image.file = poDS->fpImage;
     582              48 :     poDS->image.fileName = poOpenInfo->pszFilename;
     583                 : 
     584                 : /* -------------------------------------------------------------------- */
     585                 : /*      Capture some information from the file that is of interest.     */
     586                 : /* -------------------------------------------------------------------- */
     587              48 :     poDS->nRasterXSize = poDS->image.xsize;
     588              48 :     poDS->nRasterYSize = poDS->image.ysize;
     589              48 :     if (poDS->nRasterXSize <= 0 || poDS->nRasterYSize <= 0)
     590                 :     {
     591                 :         CPLError(CE_Failure, CPLE_OpenFailed, 
     592               0 :                      "Invalid image dimensions : %d x %d", poDS->nRasterXSize, poDS->nRasterYSize);
     593               0 :         delete poDS;
     594               0 :         return NULL;
     595                 :     }
     596              48 :     poDS->nBands = MAX(1,poDS->image.zsize);
     597              48 :     if (poDS->nBands > 256)
     598                 :     {
     599                 :         CPLError(CE_Failure, CPLE_OpenFailed, 
     600               0 :                      "Too many bands : %d", poDS->nBands);
     601               0 :         delete poDS;
     602               0 :         return NULL;
     603                 :     }
     604                 : 
     605              48 :     int numItems = (int(poDS->image.bpc) == 1) ? 256 : 65536;
     606              48 :     poDS->image.tmp = (unsigned char*)VSICalloc(poDS->image.xsize,numItems);
     607              48 :     if (poDS->image.tmp == NULL)
     608                 :     {
     609               0 :         CPLError(CE_Failure, CPLE_OutOfMemory, "Out of memory");
     610               0 :         delete poDS;
     611               0 :         return NULL;
     612                 :     }
     613                 : 
     614                 : /* -------------------------------------------------------------------- */
     615                 : /*      Read RLE Pointer tables.                                        */
     616                 : /* -------------------------------------------------------------------- */
     617              48 :     if(int(poDS->image.type) == 1) // RLE compressed
     618                 :     {
     619              48 :         int x = poDS->image.ysize * poDS->nBands * sizeof(GUInt32);
     620              48 :         poDS->image.rowStart = (GUInt32*)VSIMalloc2(poDS->image.ysize, poDS->nBands * sizeof(GUInt32));
     621              48 :         poDS->image.rowSize = (GInt32*)VSIMalloc2(poDS->image.ysize, poDS->nBands * sizeof(GUInt32));
     622              48 :         if (poDS->image.rowStart == NULL || poDS->image.rowSize == NULL)
     623                 :         {
     624               0 :             CPLError(CE_Failure, CPLE_OutOfMemory, "Out of memory");
     625               0 :             delete poDS;
     626               0 :             return NULL;
     627                 :         }
     628              48 :         memset(poDS->image.rowStart, 0, x);
     629              48 :         memset(poDS->image.rowSize, 0, x);
     630              48 :         poDS->image.rleEnd = 512 + (2 * x);
     631              48 :         VSIFSeekL(poDS->fpImage, 512, SEEK_SET);
     632              48 :         if((int) VSIFReadL(poDS->image.rowStart, 1, x, poDS->image.file) != x)
     633                 :         {
     634               4 :             delete poDS;
     635                 :             CPLError(CE_Failure, CPLE_OpenFailed, 
     636               4 :                      "file read error while reading start positions in sgidataset.cpp");
     637               4 :             return NULL;
     638                 :         }
     639              44 :         if((int) VSIFReadL(poDS->image.rowSize, 1, x, poDS->image.file) != x)
     640                 :         {
     641               0 :             delete poDS;
     642                 :             CPLError(CE_Failure, CPLE_OpenFailed, 
     643               0 :                      "file read error while reading row lengths in sgidataset.cpp");
     644               0 :             return NULL;
     645                 :         }
     646              44 :         ConvertLong(poDS->image.rowStart, x/(int)sizeof(GUInt32));
     647              44 :         ConvertLong((GUInt32*)poDS->image.rowSize, x/(int)sizeof(GInt32));
     648                 :     }
     649                 :     else // uncompressed.
     650                 :     {
     651               0 :         poDS->image.rowStart = NULL;
     652               0 :         poDS->image.rowSize = NULL;
     653                 :     }
     654                 : 
     655                 : /* -------------------------------------------------------------------- */
     656                 : /*      Create band information objects.                                */
     657                 : /* -------------------------------------------------------------------- */
     658             148 :     for(int iBand = 0; iBand < poDS->nBands; iBand++)
     659             104 :         poDS->SetBand(iBand+1, new SGIRasterBand(poDS, iBand+1));
     660                 : 
     661                 : /* -------------------------------------------------------------------- */
     662                 : /*      Check for world file.                                           */
     663                 : /* -------------------------------------------------------------------- */
     664                 :     poDS->bGeoTransformValid = 
     665                 :         GDALReadWorldFile(poOpenInfo->pszFilename, ".wld", 
     666              44 :                           poDS->adfGeoTransform);
     667                 : 
     668                 : /* -------------------------------------------------------------------- */
     669                 : /*      Initialize any PAM information.                                 */
     670                 : /* -------------------------------------------------------------------- */
     671              44 :     poDS->SetDescription(poOpenInfo->pszFilename);
     672              44 :     poDS->TryLoadXML();
     673                 : 
     674                 : /* -------------------------------------------------------------------- */
     675                 : /*      Check for overviews.                                            */
     676                 : /* -------------------------------------------------------------------- */
     677              44 :     poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
     678                 : 
     679              44 :     return poDS;
     680                 : }
     681                 : 
     682                 : /************************************************************************/
     683                 : /*                               Create()                               */
     684                 : /************************************************************************/
     685                 : 
     686              90 : GDALDataset *SGIDataset::Create( const char * pszFilename,
     687                 :                                  int nXSize, int nYSize, int nBands,
     688                 :                                  GDALDataType eType, char **papszOptions )
     689                 : 
     690                 : {
     691              90 :     if( eType != GDT_Byte )
     692                 :     {
     693                 :         CPLError( CE_Failure, CPLE_AppDefined,
     694                 :               "Attempt to create SGI dataset with an illegal\n"
     695                 :               "data type (%s), only Byte supported by the format.\n",
     696              60 :               GDALGetDataTypeName(eType) );
     697                 : 
     698              60 :         return NULL;
     699                 :     }
     700                 : 
     701                 : /* -------------------------------------------------------------------- */
     702                 : /*      Open the file for output.                                       */
     703                 : /* -------------------------------------------------------------------- */
     704              30 :     VSILFILE *fp = VSIFOpenL( pszFilename, "w" );
     705              30 :     if( fp == NULL )
     706                 :     {
     707                 :         CPLError( CE_Failure, CPLE_OpenFailed, 
     708                 :                   "Failed to create file '%s': %s", 
     709               4 :                   pszFilename, VSIStrerror( errno ) );
     710               4 :         return NULL;
     711                 :     }
     712                 :     
     713                 : /* -------------------------------------------------------------------- */
     714                 : /*      Prepare and write 512 byte header.                              */
     715                 : /* -------------------------------------------------------------------- */
     716                 :     GByte abyHeader[512];
     717                 :     GInt16 nShortValue;
     718                 :     GInt32 nIntValue;
     719                 : 
     720              26 :     memset( abyHeader, 0, 512 );
     721                 : 
     722              26 :     abyHeader[0] = 1;
     723              26 :     abyHeader[1] = 218;
     724              26 :     abyHeader[2] = 1; // RLE
     725              26 :     abyHeader[3] = 1;  // 8bit
     726                 : 
     727              26 :     if( nBands == 1 )
     728               8 :         nShortValue = CPL_MSBWORD16(2);
     729                 :     else
     730              18 :         nShortValue = CPL_MSBWORD16(3);
     731              26 :     memcpy( abyHeader + 4, &nShortValue, 2 );
     732                 :     
     733              26 :     nShortValue = CPL_MSBWORD16(nXSize);
     734              26 :     memcpy( abyHeader + 6, &nShortValue, 2 );
     735                 : 
     736              26 :     nShortValue = CPL_MSBWORD16(nYSize);
     737              26 :     memcpy( abyHeader + 8, &nShortValue, 2 );
     738                 : 
     739              26 :     nShortValue = CPL_MSBWORD16(nBands);
     740              26 :     memcpy( abyHeader + 10, &nShortValue, 2 );
     741                 : 
     742              26 :     nIntValue = CPL_MSBWORD32(0);
     743              26 :     memcpy( abyHeader + 12, &nIntValue, 4 );
     744                 :     
     745              26 :     nIntValue = CPL_MSBWORD32(255);
     746              26 :     memcpy( abyHeader + 16, &nIntValue, 4 );
     747                 :     
     748              26 :     VSIFWriteL( abyHeader, 1, 512, fp );
     749                 : 
     750                 : /* -------------------------------------------------------------------- */
     751                 : /*      Create our RLE compressed zero-ed dummy line.                   */
     752                 : /* -------------------------------------------------------------------- */
     753                 :     GByte *pabyRLELine;
     754              26 :     GInt32 nRLEBytes = 0;
     755              26 :     int   nPixelsRemaining = nXSize;
     756                 : 
     757              26 :     pabyRLELine = (GByte *) CPLMalloc((nXSize/127) * 2 + 4);
     758                 :     
     759              78 :     while( nPixelsRemaining > 0 )
     760                 :     {
     761              26 :         pabyRLELine[nRLEBytes] = (GByte) MIN(127,nPixelsRemaining);
     762              26 :         pabyRLELine[nRLEBytes+1] = 0;
     763              26 :         nPixelsRemaining -= pabyRLELine[nRLEBytes];
     764                 : 
     765              26 :         nRLEBytes += 2;
     766                 :     }
     767                 : 
     768                 : /* -------------------------------------------------------------------- */
     769                 : /*      Prepare and write RLE offset/size tables with everything        */
     770                 : /*      zeroed indicating dummy lines.                                  */
     771                 : /* -------------------------------------------------------------------- */
     772                 :     int i;
     773              26 :     int nTableLen = nYSize * nBands;
     774              26 :     GInt32 nDummyRLEOffset = 512 + 4 * nTableLen * 2;
     775                 : 
     776              26 :     CPL_MSBPTR32( &nRLEBytes );
     777              26 :     CPL_MSBPTR32( &nDummyRLEOffset );
     778                 :     
     779            3466 :     for( i = 0; i < nTableLen; i++ )
     780            3440 :         VSIFWriteL( &nDummyRLEOffset, 1, 4, fp );
     781                 : 
     782            3466 :     for( i = 0; i < nTableLen; i++ )
     783            3440 :         VSIFWriteL( &nRLEBytes, 1, 4, fp );
     784                 : 
     785                 : /* -------------------------------------------------------------------- */
     786                 : /*      write the dummy RLE blank line.                                 */
     787                 : /* -------------------------------------------------------------------- */
     788              26 :     CPL_MSBPTR32( &nRLEBytes );
     789              26 :     if( (GInt32) VSIFWriteL( pabyRLELine, 1, nRLEBytes, fp ) != nRLEBytes )
     790                 :     {
     791                 :         CPLError( CE_Failure, CPLE_FileIO,  
     792                 :                   "Failure writing SGI file '%s'.\n%s", 
     793                 :                   pszFilename, 
     794               0 :                   VSIStrerror( errno ) );
     795               0 :         return NULL;
     796                 :     }
     797                 : 
     798              26 :     VSIFCloseL( fp );
     799              26 :     CPLFree( pabyRLELine );
     800                 : 
     801              26 :     return (GDALDataset*) GDALOpen( pszFilename, GA_Update );
     802                 : }
     803                 : 
     804                 : /************************************************************************/
     805                 : /*                         GDALRegister_SGI()                          */
     806                 : /************************************************************************/
     807                 : 
     808            1135 : void GDALRegister_SGI()
     809                 : 
     810                 : {
     811                 :     GDALDriver*  poDriver;
     812                 : 
     813            1135 :     if(GDALGetDriverByName("SGI") == NULL)
     814                 :     {
     815            1093 :         poDriver = new GDALDriver();
     816                 :         
     817            1093 :         poDriver->SetDescription("SGI");
     818                 :         poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, 
     819            1093 :                                   "SGI Image File Format 1.0");
     820            1093 :         poDriver->SetMetadataItem(GDAL_DMD_EXTENSION, "rgb");
     821            1093 :         poDriver->SetMetadataItem(GDAL_DMD_MIMETYPE, "image/rgb");
     822                 :         poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
     823            1093 :                                    "frmt_various.html#SGI" );
     824            1093 :         poDriver->pfnOpen = SGIDataset::Open;
     825            1093 :         poDriver->pfnCreate = SGIDataset::Create;
     826            1093 :         poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, "Byte" );
     827            1093 :         GetGDALDriverManager()->RegisterDriver(poDriver);
     828                 :     }
     829            1135 : }
     830                 : 

Generated by: LCOV version 1.7