GDALDataset *MEMDataset::Open( GDALOpenInfo * poOpenInfo ) { char **papszOptions; /* -------------------------------------------------------------------- */ /* Do we have the special filename signature for MEM format */ /* description strings? */ /* -------------------------------------------------------------------- */ if( !EQUALN(poOpenInfo->pszFilename,"MEM:::",6) || poOpenInfo->fp != NULL ) return NULL; papszOptions = CSLTokenizeStringComplex(poOpenInfo->pszFilename+6, ",", TRUE, FALSE ); /* -------------------------------------------------------------------- */ /* Verify we have all required fields */ /* -------------------------------------------------------------------- */ if( CSLFetchNameValue( papszOptions, "PIXELS" ) == NULL || CSLFetchNameValue( papszOptions, "LINES" ) == NULL || CSLFetchNameValue( papszOptions, "DATAPOINTER" ) == NULL ) { CPLError( CE_Failure, CPLE_AppDefined, "Missing required field (one of PIXELS, LINES or DATAPOINTER)\n" "Unable to access in-memory array." ); CSLDestroy( papszOptions ); return NULL; } /* -------------------------------------------------------------------- */ /* Create the new MEMDataset object. */ /* -------------------------------------------------------------------- */ MEMDataset *poDS; poDS = new MEMDataset(); poDS->nRasterXSize = atoi(CSLFetchNameValue(papszOptions,"PIXELS")); poDS->nRasterYSize = atoi(CSLFetchNameValue(papszOptions,"LINES")); poDS->eAccess = GA_Update; /* -------------------------------------------------------------------- */ /* Extract other information. */ /* -------------------------------------------------------------------- */ const char *pszOption; GDALDataType eType; int nBands, nPixelOffset, nLineOffset; size_t nBandOffset; const char *pszDataPointer; GByte *pabyData; pszOption = CSLFetchNameValue(papszOptions,"BANDS"); if( pszOption == NULL ) nBands = 1; else { nBands = atoi(pszOption); } if (!GDALCheckDatasetDimensions(poDS->nRasterXSize, poDS->nRasterYSize) || !GDALCheckBandCount(nBands, TRUE)) { CSLDestroy( papszOptions ); delete poDS; return NULL; } pszOption = CSLFetchNameValue(papszOptions,"DATATYPE"); if( pszOption == NULL ) eType = GDT_Byte; else { if( atoi(pszOption) > 0 && atoi(pszOption) < GDT_TypeCount ) eType = (GDALDataType) atoi(pszOption); else { int iType; eType = GDT_Unknown; for( iType = 0; iType < GDT_TypeCount; iType++ ) { if( EQUAL(GDALGetDataTypeName((GDALDataType) iType), pszOption) ) { eType = (GDALDataType) iType; break; } } if( eType == GDT_Unknown ) { CPLError( CE_Failure, CPLE_AppDefined, "DATATYPE=%s not recognised.", pszOption ); CSLDestroy( papszOptions ); delete poDS; return NULL; } } } pszOption = CSLFetchNameValue(papszOptions,"PIXELOFFSET"); if( pszOption == NULL ) nPixelOffset = GDALGetDataTypeSize(eType) / 8; else nPixelOffset = atoi(pszOption); pszOption = CSLFetchNameValue(papszOptions,"LINEOFFSET"); if( pszOption == NULL ) nLineOffset = poDS->nRasterXSize * nPixelOffset; else nLineOffset = atoi(pszOption); pszOption = CSLFetchNameValue(papszOptions,"BANDOFFSET"); if( pszOption == NULL ) nBandOffset = nLineOffset * (size_t) poDS->nRasterYSize; else nBandOffset = atoi(pszOption); pszDataPointer = CSLFetchNameValue(papszOptions,"DATAPOINTER"); pabyData = (GByte *) CPLScanPointer( pszDataPointer, strlen(pszDataPointer) ); /* -------------------------------------------------------------------- */ /* Create band information objects. */ /* -------------------------------------------------------------------- */ for( int iBand = 0; iBand < nBands; iBand++ ) { poDS->SetBand( iBand+1, new MEMRasterBand( poDS, iBand+1, pabyData + iBand * nBandOffset, eType, nPixelOffset, nLineOffset, FALSE ) ); } /* -------------------------------------------------------------------- */ /* Try to return a regular handle on the file. */ /* -------------------------------------------------------------------- */ CSLDestroy( papszOptions ); return poDS; }
GDALDataset *MEMDataset::Create( const char * pszFilename, int nXSize, int nYSize, int nBands, GDALDataType eType, char **papszOptions ) { /* -------------------------------------------------------------------- */ /* Do we want a pixel interleaved buffer? I mostly care about */ /* this to test pixel interleaved io in other contexts, but it */ /* could be useful to create a directly accessable buffer for */ /* some apps. */ /* -------------------------------------------------------------------- */ int bPixelInterleaved = FALSE; const char *pszOption = CSLFetchNameValue( papszOptions, "INTERLEAVE" ); if( pszOption && EQUAL(pszOption,"PIXEL") ) bPixelInterleaved = TRUE; /* -------------------------------------------------------------------- */ /* First allocate band data, verifying that we can get enough */ /* memory. */ /* -------------------------------------------------------------------- */ std::vector<GByte*> apbyBandData; int iBand; int nWordSize = GDALGetDataTypeSize(eType) / 8; int bAllocOK = TRUE; if( bPixelInterleaved ) { apbyBandData.push_back( (GByte *) VSIMalloc3( nWordSize * nBands, nXSize, nYSize ) ); if( apbyBandData[0] == NULL ) bAllocOK = FALSE; else { memset(apbyBandData[0], 0, ((size_t)nWordSize) * nBands * nXSize * nYSize); for( iBand = 1; iBand < nBands; iBand++ ) apbyBandData.push_back( apbyBandData[0] + iBand * nWordSize ); } } else { for( iBand = 0; iBand < nBands; iBand++ ) { apbyBandData.push_back( (GByte *) VSIMalloc3( nWordSize, nXSize, nYSize ) ); if( apbyBandData[iBand] == NULL ) { bAllocOK = FALSE; break; } memset(apbyBandData[iBand], 0, ((size_t)nWordSize) * nXSize * nYSize); } } if( !bAllocOK ) { for( iBand = 0; iBand < (int) apbyBandData.size(); iBand++ ) { if( apbyBandData[iBand] ) VSIFree( apbyBandData[iBand] ); } CPLError( CE_Failure, CPLE_OutOfMemory, "Unable to create band arrays ... out of memory." ); return NULL; } /* -------------------------------------------------------------------- */ /* Create the new GTiffDataset object. */ /* -------------------------------------------------------------------- */ MEMDataset *poDS; poDS = new MEMDataset(); poDS->nRasterXSize = nXSize; poDS->nRasterYSize = nYSize; poDS->eAccess = GA_Update; if( bPixelInterleaved ) poDS->SetMetadataItem( "INTERLEAVE", "PIXEL", "IMAGE_STRUCTURE" ); /* -------------------------------------------------------------------- */ /* Create band information objects. */ /* -------------------------------------------------------------------- */ for( iBand = 0; iBand < nBands; iBand++ ) { MEMRasterBand *poNewBand; if( bPixelInterleaved ) poNewBand = new MEMRasterBand( poDS, iBand+1, apbyBandData[iBand], eType, nWordSize * nBands, 0, iBand == 0 ); else poNewBand = new MEMRasterBand( poDS, iBand+1, apbyBandData[iBand], eType, 0, 0, TRUE ); poDS->SetBand( iBand+1, poNewBand ); } /* -------------------------------------------------------------------- */ /* Try to return a regular handle on the file. */ /* -------------------------------------------------------------------- */ return poDS; }
GDALDataset *MEMDataset::Create( const char * /* pszFilename */, int nXSize, int nYSize, int nBands, GDALDataType eType, char **papszOptions ) { /* -------------------------------------------------------------------- */ /* Do we want a pixel interleaved buffer? I mostly care about */ /* this to test pixel interleaved IO in other contexts, but it */ /* could be useful to create a directly accessible buffer for */ /* some apps. */ /* -------------------------------------------------------------------- */ bool bPixelInterleaved = false; const char *pszOption = CSLFetchNameValue( papszOptions, "INTERLEAVE" ); if( pszOption && EQUAL(pszOption,"PIXEL") ) bPixelInterleaved = true; /* -------------------------------------------------------------------- */ /* First allocate band data, verifying that we can get enough */ /* memory. */ /* -------------------------------------------------------------------- */ const int nWordSize = GDALGetDataTypeSize(eType) / 8; if( nBands > 0 && nWordSize > 0 && (nBands > INT_MAX / nWordSize || (GIntBig)nXSize * nYSize > GINTBIG_MAX / (nWordSize * nBands)) ) { CPLError( CE_Failure, CPLE_OutOfMemory, "Multiplication overflow"); return NULL; } const GUIntBig nGlobalBigSize = static_cast<GUIntBig>(nWordSize) * nBands * nXSize * nYSize; const size_t nGlobalSize = static_cast<size_t>(nGlobalBigSize); #if SIZEOF_VOIDP == 4 if( static_cast<GUIntBig>(nGlobalSize) != nGlobalBigSize ) { CPLError( CE_Failure, CPLE_OutOfMemory, "Cannot allocate " CPL_FRMT_GUIB " bytes on this platform.", nGlobalBigSize ); return NULL; } #endif std::vector<GByte*> apbyBandData; bool bAllocOK = true; if( bPixelInterleaved ) { apbyBandData.push_back( reinterpret_cast<GByte *>( VSI_CALLOC_VERBOSE( 1, nGlobalSize ) ) ); if( apbyBandData[0] == NULL ) bAllocOK = FALSE; else { for( int iBand = 1; iBand < nBands; iBand++ ) apbyBandData.push_back( apbyBandData[0] + iBand * nWordSize ); } } else { for( int iBand = 0; iBand < nBands; iBand++ ) { apbyBandData.push_back( reinterpret_cast<GByte *>( VSI_CALLOC_VERBOSE( 1, static_cast<size_t>(nWordSize) * nXSize * nYSize ) ) ); if( apbyBandData[iBand] == NULL ) { bAllocOK = FALSE; break; } } } if( !bAllocOK ) { for( int iBand = 0; iBand < static_cast<int>( apbyBandData.size() ); iBand++ ) { if( apbyBandData[iBand] ) VSIFree( apbyBandData[iBand] ); } return NULL; } /* -------------------------------------------------------------------- */ /* Create the new GTiffDataset object. */ /* -------------------------------------------------------------------- */ MEMDataset *poDS = new MEMDataset(); poDS->nRasterXSize = nXSize; poDS->nRasterYSize = nYSize; poDS->eAccess = GA_Update; const char *pszPixelType = CSLFetchNameValue( papszOptions, "PIXELTYPE" ); if( pszPixelType && EQUAL(pszPixelType, "SIGNEDBYTE") ) poDS->SetMetadataItem( "PIXELTYPE", "SIGNEDBYTE", "IMAGE_STRUCTURE" ); if( bPixelInterleaved ) poDS->SetMetadataItem( "INTERLEAVE", "PIXEL", "IMAGE_STRUCTURE" ); /* -------------------------------------------------------------------- */ /* Create band information objects. */ /* -------------------------------------------------------------------- */ for( int iBand = 0; iBand < nBands; iBand++ ) { MEMRasterBand *poNewBand = NULL; if( bPixelInterleaved ) poNewBand = new MEMRasterBand( poDS, iBand+1, apbyBandData[iBand], eType, nWordSize * nBands, 0, iBand == 0 ); else poNewBand = new MEMRasterBand( poDS, iBand+1, apbyBandData[iBand], eType, 0, 0, TRUE ); poDS->SetBand( iBand+1, poNewBand ); } /* -------------------------------------------------------------------- */ /* Try to return a regular handle on the file. */ /* -------------------------------------------------------------------- */ return poDS; }