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; }