LCOV - code coverage report
Current view: directory - frmts/raw - pnmdataset.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 148 127 85.8 %
Date: 2010-01-09 Functions: 8 8 100.0 %

       1                 : /******************************************************************************
       2                 :  * $Id: pnmdataset.cpp 16865 2009-04-27 12:49:49Z chaitanya $
       3                 :  *
       4                 :  * Project:  PNM Driver
       5                 :  * Purpose:  Portable anymap file format imlementation
       6                 :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       7                 :  *
       8                 :  ******************************************************************************
       9                 :  * Copyright (c) 2001, Frank Warmerdam
      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 "rawdataset.h"
      31                 : #include "cpl_string.h"
      32                 : #include <ctype.h>
      33                 : 
      34                 : CPL_CVSID("$Id: pnmdataset.cpp 16865 2009-04-27 12:49:49Z chaitanya $");
      35                 : 
      36                 : CPL_C_START
      37                 : void    GDALRegister_PNM(void);
      38                 : CPL_C_END
      39                 : 
      40                 : /************************************************************************/
      41                 : /* ==================================================================== */
      42                 : /*                              PNMDataset                              */
      43                 : /* ==================================================================== */
      44                 : /************************************************************************/
      45                 : 
      46                 : class PNMDataset : public RawDataset
      47                 : {
      48                 :     FILE        *fpImage;       // image data file.
      49                 : 
      50                 :     int         bGeoTransformValid;
      51                 :     double      adfGeoTransform[6];
      52                 : 
      53                 :   public:
      54                 :                 PNMDataset();
      55                 :                 ~PNMDataset();
      56                 : 
      57                 :     virtual CPLErr GetGeoTransform( double * );
      58                 : 
      59                 :     static int          Identify( GDALOpenInfo * );
      60                 :     static GDALDataset *Open( GDALOpenInfo * );
      61                 :     static GDALDataset *Create( const char * pszFilename,
      62                 :                                 int nXSize, int nYSize, int nBands,
      63                 :                                 GDALDataType eType, char ** papszOptions );
      64                 : };
      65                 : 
      66                 : /************************************************************************/
      67                 : /*                            PNMDataset()                             */
      68                 : /************************************************************************/
      69                 : 
      70              40 : PNMDataset::PNMDataset()
      71                 : {
      72              40 :     fpImage = NULL;
      73              40 :     bGeoTransformValid = FALSE;
      74              40 :     adfGeoTransform[0] = 0.0;
      75              40 :     adfGeoTransform[1] = 1.0;
      76              40 :     adfGeoTransform[2] = 0.0;
      77              40 :     adfGeoTransform[3] = 0.0;
      78              40 :     adfGeoTransform[4] = 0.0;
      79              40 :     adfGeoTransform[5] = 1.0;
      80              40 : }
      81                 : 
      82                 : /************************************************************************/
      83                 : /*                            ~PNMDataset()                            */
      84                 : /************************************************************************/
      85                 : 
      86              80 : PNMDataset::~PNMDataset()
      87                 : 
      88                 : {
      89              40 :     FlushCache();
      90              40 :     if( fpImage != NULL )
      91              40 :         VSIFCloseL( fpImage );
      92              80 : }
      93                 : 
      94                 : /************************************************************************/
      95                 : /*                          GetGeoTransform()                           */
      96                 : /************************************************************************/
      97                 : 
      98               4 : CPLErr PNMDataset::GetGeoTransform( double * padfTransform )
      99                 : 
     100                 : {
     101                 : 
     102               4 :     if( bGeoTransformValid )
     103                 :     {
     104               0 :         memcpy( padfTransform, adfGeoTransform, sizeof(double)*6 );
     105               0 :         return CE_None;
     106                 :     }
     107                 :     else
     108               4 :         return CE_Failure;
     109                 : }
     110                 : 
     111                 : /************************************************************************/
     112                 : /*                              Identify()                              */
     113                 : /************************************************************************/
     114                 : 
     115            8776 : int PNMDataset::Identify( GDALOpenInfo * poOpenInfo )
     116                 : 
     117                 : {
     118                 : /* -------------------------------------------------------------------- */
     119                 : /*      Verify that this is a _raw_ ppm or pgm file.  Note, we don't    */
     120                 : /*      support ascii files, or pbm (1bit) files.                       */
     121                 : /* -------------------------------------------------------------------- */
     122            8776 :     if( poOpenInfo->nHeaderBytes < 10 || poOpenInfo->fp == NULL )
     123            8426 :         return FALSE;
     124                 : 
     125             490 :     if( poOpenInfo->pabyHeader[0] != 'P'  ||
     126              45 :         (poOpenInfo->pabyHeader[2] != ' '  &&    // XXX: Magick number
     127              45 :          poOpenInfo->pabyHeader[2] != '\t' &&    // may be followed
     128              45 :          poOpenInfo->pabyHeader[2] != '\n' &&    // any of the blank
     129               5 :          poOpenInfo->pabyHeader[2] != '\r') )    // characters
     130             310 :         return FALSE;
     131                 : 
     132              57 :     if( poOpenInfo->pabyHeader[1] != '5'
     133              17 :         && poOpenInfo->pabyHeader[1] != '6' )
     134               0 :         return FALSE;
     135                 : 
     136              40 :     return TRUE;
     137                 : }
     138                 : 
     139                 : /************************************************************************/
     140                 : /*                                Open()                                */
     141                 : /************************************************************************/
     142                 : 
     143            1049 : GDALDataset *PNMDataset::Open( GDALOpenInfo * poOpenInfo )
     144                 : 
     145                 : {
     146                 : /* -------------------------------------------------------------------- */
     147                 : /*      Verify that this is a _raw_ ppm or pgm file.  Note, we don't    */
     148                 : /*      support ascii files, or pbm (1bit) files.                       */
     149                 : /* -------------------------------------------------------------------- */
     150            1049 :     if( !Identify( poOpenInfo ) )
     151            1009 :         return NULL;
     152                 : 
     153                 : /* -------------------------------------------------------------------- */
     154                 : /*      Parse out the tokens from the header.                           */
     155                 : /* -------------------------------------------------------------------- */
     156              40 :     const char  *pszSrc = (const char *) poOpenInfo->pabyHeader;
     157                 :     char        szToken[512];
     158              40 :     int         iIn, iToken = 0, nWidth =-1, nHeight=-1, nMaxValue=-1;
     159                 :     unsigned int iOut;
     160                 : 
     161              40 :     iIn = 2;
     162             200 :     while( iIn < poOpenInfo->nHeaderBytes && iToken < 3 )
     163                 :     {
     164             120 :         iOut = 0;
     165             120 :         szToken[0] = '\0';
     166             595 :         while( iOut < sizeof(szToken) && iIn < poOpenInfo->nHeaderBytes )
     167                 :         {
     168             475 :             if( pszSrc[iIn] == '#' )
     169                 :             {
     170               0 :                 while( pszSrc[iIn] != 10 && pszSrc[iIn] != 13
     171                 :                        && iIn < poOpenInfo->nHeaderBytes - 1 )
     172               0 :                     iIn++;
     173                 :             }
     174                 : 
     175             475 :             if( iOut != 0 && isspace((unsigned char)pszSrc[iIn]) )
     176                 :             {
     177             120 :                 szToken[iOut] = '\0';
     178                 : 
     179             120 :                 if( iToken == 0 )
     180              40 :                     nWidth = atoi(szToken);
     181              80 :                 else if( iToken == 1 )
     182              40 :                     nHeight = atoi(szToken);
     183              40 :                 else if( iToken == 2 )
     184              40 :                     nMaxValue = atoi(szToken);
     185                 : 
     186             120 :                 iToken++;
     187             120 :                 iIn++;
     188             120 :                 break;
     189                 :             }
     190                 : 
     191             355 :             else if( !isspace((unsigned char)pszSrc[iIn]) )
     192                 :             {
     193             315 :                 szToken[iOut++] = pszSrc[iIn];
     194                 :             }
     195                 : 
     196             355 :             iIn++;
     197                 :         }
     198                 :     }
     199                 : 
     200                 :     CPLDebug( "PNM", "PNM header contains: width=%d, height=%d, maxval=%d",
     201              40 :               nWidth, nHeight, nMaxValue );
     202                 : 
     203              40 :     if( iToken != 3 || nWidth < 1 || nHeight < 1 || nMaxValue < 1 )
     204               0 :         return NULL;
     205                 : 
     206                 : /* -------------------------------------------------------------------- */
     207                 : /*      Create a corresponding GDALDataset.                             */
     208                 : /* -------------------------------------------------------------------- */
     209                 :     PNMDataset  *poDS;
     210                 : 
     211              40 :     poDS = new PNMDataset();
     212                 : 
     213                 : /* -------------------------------------------------------------------- */
     214                 : /*      Capture some information from the file that is of interest.     */
     215                 : /* -------------------------------------------------------------------- */
     216              40 :     poDS->nRasterXSize = nWidth;
     217              40 :     poDS->nRasterYSize = nHeight;
     218                 : 
     219                 : /* -------------------------------------------------------------------- */
     220                 : /*      Assume ownership of the file handled from the GDALOpenInfo.     */
     221                 : /* -------------------------------------------------------------------- */
     222              40 :     VSIFClose( poOpenInfo->fp );
     223              40 :     poOpenInfo->fp = NULL;
     224                 : 
     225              40 :     if( poOpenInfo->eAccess == GA_Update )
     226              16 :         poDS->fpImage = VSIFOpenL( poOpenInfo->pszFilename, "rb+" );
     227                 :     else
     228              24 :         poDS->fpImage = VSIFOpenL( poOpenInfo->pszFilename, "rb" );
     229                 : 
     230              40 :     if( poDS->fpImage == NULL )
     231                 :     {
     232                 :         CPLError( CE_Failure, CPLE_OpenFailed,
     233                 :                   "Failed to re-open %s within PNM driver.\n",
     234               0 :                   poOpenInfo->pszFilename );
     235               0 :         return NULL;
     236                 :     }
     237                 : 
     238              40 :     poDS->eAccess = poOpenInfo->eAccess;
     239                 : 
     240                 : /* -------------------------------------------------------------------- */
     241                 : /*      Create band information objects.                                */
     242                 : /* -------------------------------------------------------------------- */
     243              40 :     int         bMSBFirst = TRUE, iPixelSize;
     244                 :     GDALDataType eDataType;
     245                 : 
     246                 : #ifdef CPL_LSB
     247              40 :     bMSBFirst = FALSE;
     248                 : #endif
     249                 : 
     250              40 :     if ( nMaxValue < 256 )
     251              31 :         eDataType = GDT_Byte;
     252                 :     else
     253               9 :         eDataType = GDT_UInt16;
     254                 : 
     255              40 :     iPixelSize = GDALGetDataTypeSize( eDataType ) / 8;
     256                 : 
     257              40 :     if( poOpenInfo->pabyHeader[1] == '5' )
     258                 :     {
     259              23 :         if (nWidth > INT_MAX / iPixelSize)
     260                 :         {
     261                 :             CPLError( CE_Failure, CPLE_AppDefined, 
     262               0 :                   "Int overflow occured.");
     263               0 :             delete poDS;
     264               0 :             return NULL;
     265                 :         }
     266                 :         poDS->SetBand(
     267                 :             1, new RawRasterBand( poDS, 1, poDS->fpImage, iIn, iPixelSize,
     268              23 :                                   nWidth*iPixelSize, eDataType, bMSBFirst, TRUE ));
     269              23 :         poDS->GetRasterBand(1)->SetColorInterpretation( GCI_GrayIndex );
     270                 :     }
     271                 :     else
     272                 :     {
     273              17 :         if (nWidth > INT_MAX / (3 * iPixelSize))
     274                 :         {
     275                 :             CPLError( CE_Failure, CPLE_AppDefined, 
     276               0 :                   "Int overflow occured.");
     277               0 :             delete poDS;
     278               0 :             return NULL;
     279                 :         }
     280                 :         poDS->SetBand(
     281                 :             1, new RawRasterBand( poDS, 1, poDS->fpImage, iIn, 3*iPixelSize,
     282              17 :                                   nWidth*3*iPixelSize, eDataType, bMSBFirst, TRUE ));
     283                 :         poDS->SetBand(
     284                 :             2, new RawRasterBand( poDS, 2, poDS->fpImage, iIn+iPixelSize,
     285                 :                                   3*iPixelSize, nWidth*3*iPixelSize,
     286              34 :                                   eDataType, bMSBFirst, TRUE ));
     287                 :         poDS->SetBand(
     288                 :             3, new RawRasterBand( poDS, 3, poDS->fpImage, iIn+2*iPixelSize,
     289                 :                                   3*iPixelSize, nWidth*3*iPixelSize,
     290              34 :                                   eDataType, bMSBFirst, TRUE ));
     291                 : 
     292              17 :         poDS->GetRasterBand(1)->SetColorInterpretation( GCI_RedBand );
     293              17 :         poDS->GetRasterBand(2)->SetColorInterpretation( GCI_GreenBand );
     294              17 :         poDS->GetRasterBand(3)->SetColorInterpretation( GCI_BlueBand );
     295                 :     }
     296                 : 
     297                 : /* -------------------------------------------------------------------- */
     298                 : /*      Check for world file.                                           */
     299                 : /* -------------------------------------------------------------------- */
     300                 :     poDS->bGeoTransformValid = 
     301                 :         GDALReadWorldFile( poOpenInfo->pszFilename, ".wld", 
     302              40 :                            poDS->adfGeoTransform );
     303                 : 
     304                 : /* -------------------------------------------------------------------- */
     305                 : /*      Initialize any PAM information.                                 */
     306                 : /* -------------------------------------------------------------------- */
     307              40 :     poDS->SetDescription( poOpenInfo->pszFilename );
     308              40 :     poDS->TryLoadXML();
     309                 : 
     310                 : /* -------------------------------------------------------------------- */
     311                 : /*      Check for overviews.                                            */
     312                 : /* -------------------------------------------------------------------- */
     313              40 :     poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
     314                 : 
     315              40 :     return( poDS );
     316                 : }
     317                 : 
     318                 : /************************************************************************/
     319                 : /*                               Create()                               */
     320                 : /************************************************************************/
     321                 : 
     322              40 : GDALDataset *PNMDataset::Create( const char * pszFilename,
     323                 :                                  int nXSize, int nYSize, int nBands,
     324                 :                                  GDALDataType eType,
     325                 :                                  char ** papszOptions )
     326                 : 
     327                 : {
     328                 : /* -------------------------------------------------------------------- */
     329                 : /*      Verify input options.                                           */
     330                 : /* -------------------------------------------------------------------- */
     331              40 :     if( eType != GDT_Byte && eType != GDT_UInt16 )
     332                 :     {
     333                 :         CPLError( CE_Failure, CPLE_AppDefined,
     334                 :               "Attempt to create PNM dataset with an illegal\n"
     335                 :               "data type (%s), only Byte and UInt16 supported.\n",
     336              18 :               GDALGetDataTypeName(eType) );
     337                 : 
     338              18 :         return NULL;
     339                 :     }
     340                 : 
     341              22 :     if( nBands != 1 && nBands != 3 )
     342                 :     {
     343                 :         CPLError( CE_Failure, CPLE_AppDefined,
     344                 :                   "Attempt to create PNM dataset with an illegal number\n"
     345                 :                   "of bands (%d).  Must be 1 (greyscale) or 3 (RGB).\n",
     346               7 :                   nBands );
     347                 : 
     348               7 :         return NULL;
     349                 :     }
     350                 : 
     351                 : /* -------------------------------------------------------------------- */
     352                 : /*      Try to create the file.                                         */
     353                 : /* -------------------------------------------------------------------- */
     354                 :     FILE        *fp;
     355                 : 
     356              15 :     fp = VSIFOpenL( pszFilename, "wb" );
     357                 : 
     358              15 :     if( fp == NULL )
     359                 :     {
     360                 :         CPLError( CE_Failure, CPLE_OpenFailed,
     361                 :                   "Attempt to create file `%s' failed.\n",
     362               0 :                   pszFilename );
     363               0 :         return NULL;
     364                 :     }
     365                 : 
     366                 : /* -------------------------------------------------------------------- */
     367                 : /*      Write out the header.                                           */
     368                 : /* -------------------------------------------------------------------- */
     369                 :     char        szHeader[500];
     370              15 :     const char  *pszMaxValue = NULL;
     371              15 :     int         nMaxValue = 0;
     372                 : 
     373              15 :     pszMaxValue = CSLFetchNameValue( papszOptions, "MAXVAL" );
     374              15 :     if ( pszMaxValue )
     375                 :     {
     376               0 :         nMaxValue = atoi( pszMaxValue );
     377               0 :         if ( eType == GDT_Byte && (nMaxValue > 255 || nMaxValue < 0) )
     378               0 :             nMaxValue = 255;
     379               0 :         else if ( nMaxValue > 65535 || nMaxValue < 0 )
     380               0 :             nMaxValue = 65535;
     381                 :     }
     382                 :     else
     383                 :     {
     384              15 :         if ( eType == GDT_Byte )
     385              11 :             nMaxValue = 255;
     386                 :         else
     387               4 :             nMaxValue = 65535;
     388                 :     }
     389                 : 
     390                 : 
     391              15 :     memset( szHeader, 0, sizeof(szHeader) );
     392                 : 
     393              15 :     if( nBands == 3 )
     394               6 :         sprintf( szHeader, "P6\n%d %d\n%d\n", nXSize, nYSize, nMaxValue );
     395                 :     else
     396               9 :         sprintf( szHeader, "P5\n%d %d\n%d\n", nXSize, nYSize, nMaxValue );
     397                 : 
     398              15 :     VSIFWriteL( (void *) szHeader, strlen(szHeader) + 2, 1, fp );
     399              15 :     VSIFCloseL( fp );
     400                 : 
     401              15 :     return (GDALDataset *) GDALOpen( pszFilename, GA_Update );
     402                 : }
     403                 : 
     404                 : /************************************************************************/
     405                 : /*                         GDALRegister_PNM()                          */
     406                 : /************************************************************************/
     407                 : 
     408             338 : void GDALRegister_PNM()
     409                 : 
     410                 : {
     411                 :     GDALDriver  *poDriver;
     412                 : 
     413             338 :     if( GDALGetDriverByName( "PNM" ) == NULL )
     414                 :     {
     415             336 :         poDriver = new GDALDriver();
     416                 : 
     417             336 :         poDriver->SetDescription( "PNM" );
     418                 :         poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
     419             336 :                                    "Portable Pixmap Format (netpbm)" );
     420                 :         poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
     421             336 :                                    "frmt_various.html#PNM" );
     422             336 :         poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "pnm" );
     423                 :         poDriver->SetMetadataItem( GDAL_DMD_MIMETYPE,
     424             336 :                                    "image/x-portable-anymap" );
     425                 :         poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES,
     426             336 :                                    "Byte UInt16" );
     427                 :         poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
     428                 : "<CreationOptionList>"
     429                 : "   <Option name='MAXVAL' type='unsigned int' description='Maximum color value'/>"
     430             336 : "</CreationOptionList>" );
     431                 : 
     432             336 :         poDriver->pfnOpen = PNMDataset::Open;
     433             336 :         poDriver->pfnCreate = PNMDataset::Create;
     434             336 :         poDriver->pfnIdentify = PNMDataset::Identify;
     435                 : 
     436             336 :         GetGDALDriverManager()->RegisterDriver( poDriver );
     437                 :     }
     438             338 : }

Generated by: LCOV version 1.7