GDALDataset *PNMDataset::Open( GDALOpenInfo * poOpenInfo ) { /* -------------------------------------------------------------------- */ /* Verify that this is a _raw_ ppm or pgm file. Note, we don't */ /* support ascii files, or pbm (1bit) files. */ /* -------------------------------------------------------------------- */ if( !Identify( poOpenInfo ) ) return NULL; /* -------------------------------------------------------------------- */ /* Parse out the tokens from the header. */ /* -------------------------------------------------------------------- */ const char *pszSrc = (const char *) poOpenInfo->pabyHeader; char szToken[512]; int iIn, iToken = 0, nWidth =-1, nHeight=-1, nMaxValue=-1; unsigned int iOut; iIn = 2; while( iIn < poOpenInfo->nHeaderBytes && iToken < 3 ) { iOut = 0; szToken[0] = '\0'; while( iOut < sizeof(szToken) && iIn < poOpenInfo->nHeaderBytes ) { if( pszSrc[iIn] == '#' ) { while( pszSrc[iIn] != 10 && pszSrc[iIn] != 13 && iIn < poOpenInfo->nHeaderBytes - 1 ) iIn++; } if( iOut != 0 && isspace((unsigned char)pszSrc[iIn]) ) { szToken[iOut] = '\0'; if( iToken == 0 ) nWidth = atoi(szToken); else if( iToken == 1 ) nHeight = atoi(szToken); else if( iToken == 2 ) nMaxValue = atoi(szToken); iToken++; iIn++; break; } else if( !isspace((unsigned char)pszSrc[iIn]) ) { szToken[iOut++] = pszSrc[iIn]; } iIn++; } } CPLDebug( "PNM", "PNM header contains: width=%d, height=%d, maxval=%d", nWidth, nHeight, nMaxValue ); if( iToken != 3 || nWidth < 1 || nHeight < 1 || nMaxValue < 1 ) return NULL; /* -------------------------------------------------------------------- */ /* Create a corresponding GDALDataset. */ /* -------------------------------------------------------------------- */ PNMDataset *poDS; poDS = new PNMDataset(); /* -------------------------------------------------------------------- */ /* Capture some information from the file that is of interest. */ /* -------------------------------------------------------------------- */ poDS->nRasterXSize = nWidth; poDS->nRasterYSize = nHeight; /* -------------------------------------------------------------------- */ /* Open file */ /* -------------------------------------------------------------------- */ if( poOpenInfo->eAccess == GA_Update ) poDS->fpImage = VSIFOpenL( poOpenInfo->pszFilename, "rb+" ); else poDS->fpImage = VSIFOpenL( poOpenInfo->pszFilename, "rb" ); if( poDS->fpImage == NULL ) { CPLError( CE_Failure, CPLE_OpenFailed, "Failed to re-open %s within PNM driver.\n", poOpenInfo->pszFilename ); return NULL; } poDS->eAccess = poOpenInfo->eAccess; /* -------------------------------------------------------------------- */ /* Create band information objects. */ /* -------------------------------------------------------------------- */ int bMSBFirst = TRUE, iPixelSize; GDALDataType eDataType; #ifdef CPL_LSB bMSBFirst = FALSE; #endif if ( nMaxValue < 256 ) eDataType = GDT_Byte; else eDataType = GDT_UInt16; iPixelSize = GDALGetDataTypeSize( eDataType ) / 8; if( poOpenInfo->pabyHeader[1] == '5' ) { if (nWidth > INT_MAX / iPixelSize) { CPLError( CE_Failure, CPLE_AppDefined, "Int overflow occured."); delete poDS; return NULL; } poDS->SetBand( 1, new RawRasterBand( poDS, 1, poDS->fpImage, iIn, iPixelSize, nWidth*iPixelSize, eDataType, bMSBFirst, TRUE )); poDS->GetRasterBand(1)->SetColorInterpretation( GCI_GrayIndex ); } else { if (nWidth > INT_MAX / (3 * iPixelSize)) { CPLError( CE_Failure, CPLE_AppDefined, "Int overflow occured."); delete poDS; return NULL; } poDS->SetBand( 1, new RawRasterBand( poDS, 1, poDS->fpImage, iIn, 3*iPixelSize, nWidth*3*iPixelSize, eDataType, bMSBFirst, TRUE )); poDS->SetBand( 2, new RawRasterBand( poDS, 2, poDS->fpImage, iIn+iPixelSize, 3*iPixelSize, nWidth*3*iPixelSize, eDataType, bMSBFirst, TRUE )); poDS->SetBand( 3, new RawRasterBand( poDS, 3, poDS->fpImage, iIn+2*iPixelSize, 3*iPixelSize, nWidth*3*iPixelSize, eDataType, bMSBFirst, TRUE )); poDS->GetRasterBand(1)->SetColorInterpretation( GCI_RedBand ); poDS->GetRasterBand(2)->SetColorInterpretation( GCI_GreenBand ); poDS->GetRasterBand(3)->SetColorInterpretation( GCI_BlueBand ); } /* -------------------------------------------------------------------- */ /* Check for world file. */ /* -------------------------------------------------------------------- */ poDS->bGeoTransformValid = GDALReadWorldFile( poOpenInfo->pszFilename, ".wld", poDS->adfGeoTransform ); /* -------------------------------------------------------------------- */ /* Initialize any PAM information. */ /* -------------------------------------------------------------------- */ poDS->SetDescription( poOpenInfo->pszFilename ); poDS->TryLoadXML(); /* -------------------------------------------------------------------- */ /* Check for overviews. */ /* -------------------------------------------------------------------- */ poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename ); return( poDS ); }
GDALDataset *PNMDataset::Open( GDALOpenInfo * poOpenInfo ) { /* -------------------------------------------------------------------- */ /* Verify that this is a _raw_ ppm or pgm file. Note, we don't */ /* support ascii files, or pbm (1bit) files. */ /* -------------------------------------------------------------------- */ if( !Identify( poOpenInfo ) ) return nullptr; /* -------------------------------------------------------------------- */ /* Parse out the tokens from the header. */ /* -------------------------------------------------------------------- */ const char *pszSrc = reinterpret_cast<char *>( poOpenInfo->pabyHeader ); char szToken[512] = { '\0' }; int iToken = 0; int nWidth = -1; int nHeight = -1; int nMaxValue = -1; int iIn = 2; while( iIn < poOpenInfo->nHeaderBytes && iToken < 3 ) { unsigned int iOut = 0; szToken[0] = '\0'; while( iOut < sizeof(szToken) && iIn < poOpenInfo->nHeaderBytes ) { if( pszSrc[iIn] == '#' ) { while( iIn < poOpenInfo->nHeaderBytes - 1 && pszSrc[iIn] != 10 && pszSrc[iIn] != 13 ) iIn++; } if( iOut != 0 && isspace(static_cast<unsigned char>(pszSrc[iIn])) ) { szToken[iOut] = '\0'; if( iToken == 0 ) nWidth = atoi(szToken); else if( iToken == 1 ) nHeight = atoi(szToken); else if( iToken == 2 ) nMaxValue = atoi(szToken); iToken++; iIn++; break; } else if( !isspace(static_cast<unsigned char>(pszSrc[iIn])) ) { szToken[iOut++] = pszSrc[iIn]; } iIn++; } } CPLDebug( "PNM", "PNM header contains: width=%d, height=%d, maxval=%d", nWidth, nHeight, nMaxValue ); if( iToken != 3 || nWidth < 1 || nHeight < 1 || nMaxValue < 1 ) return nullptr; /* -------------------------------------------------------------------- */ /* Create a corresponding GDALDataset. */ /* -------------------------------------------------------------------- */ PNMDataset *poDS = new PNMDataset(); /* -------------------------------------------------------------------- */ /* Capture some information from the file that is of interest. */ /* -------------------------------------------------------------------- */ poDS->nRasterXSize = nWidth; poDS->nRasterYSize = nHeight; // Borrow file pointer poDS->fpImage = poOpenInfo->fpL; poOpenInfo->fpL = nullptr; poDS->eAccess = poOpenInfo->eAccess; /* -------------------------------------------------------------------- */ /* Create band information objects. */ /* -------------------------------------------------------------------- */ #ifdef CPL_LSB const bool bMSBFirst = false; #else const bool bMSBFirst = true; #endif GDALDataType eDataType = GDT_Unknown; if ( nMaxValue < 256 ) eDataType = GDT_Byte; else eDataType = GDT_UInt16; const int iPixelSize = GDALGetDataTypeSizeBytes( eDataType ); if( poOpenInfo->pabyHeader[1] == '5' ) { if (nWidth > INT_MAX / iPixelSize) { CPLError( CE_Failure, CPLE_AppDefined, "Int overflow occurred."); delete poDS; return nullptr; } poDS->SetBand( 1, new RawRasterBand( poDS, 1, poDS->fpImage, iIn, iPixelSize, nWidth*iPixelSize, eDataType, bMSBFirst, RawRasterBand::OwnFP::NO ) ); poDS->GetRasterBand(1)->SetColorInterpretation( GCI_GrayIndex ); } else { if (nWidth > INT_MAX / (3 * iPixelSize)) { CPLError( CE_Failure, CPLE_AppDefined, "Int overflow occurred."); delete poDS; return nullptr; } poDS->SetBand( 1, new RawRasterBand( poDS, 1, poDS->fpImage, iIn, 3*iPixelSize, nWidth*3*iPixelSize, eDataType, bMSBFirst, RawRasterBand::OwnFP::NO )); poDS->SetBand( 2, new RawRasterBand( poDS, 2, poDS->fpImage, iIn+iPixelSize, 3*iPixelSize, nWidth*3*iPixelSize, eDataType, bMSBFirst, RawRasterBand::OwnFP::NO )); poDS->SetBand( 3, new RawRasterBand( poDS, 3, poDS->fpImage, iIn+2*iPixelSize, 3*iPixelSize, nWidth*3*iPixelSize, eDataType, bMSBFirst, RawRasterBand::OwnFP::NO )); poDS->GetRasterBand(1)->SetColorInterpretation( GCI_RedBand ); poDS->GetRasterBand(2)->SetColorInterpretation( GCI_GreenBand ); poDS->GetRasterBand(3)->SetColorInterpretation( GCI_BlueBand ); } /* -------------------------------------------------------------------- */ /* Check for world file. */ /* -------------------------------------------------------------------- */ poDS->bGeoTransformValid = CPL_TO_BOOL( GDALReadWorldFile( poOpenInfo->pszFilename, ".wld", poDS->adfGeoTransform ) ); /* -------------------------------------------------------------------- */ /* Initialize any PAM information. */ /* -------------------------------------------------------------------- */ poDS->SetDescription( poOpenInfo->pszFilename ); poDS->TryLoadXML(); /* -------------------------------------------------------------------- */ /* Check for overviews. */ /* -------------------------------------------------------------------- */ poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename ); return poDS; }