CPLErr RawRasterBand::IRasterIO( GDALRWFlag eRWFlag, int nXOff, int nYOff, int nXSize, int nYSize, void * pData, int nBufXSize, int nBufYSize, GDALDataType eBufType, int nPixelSpace, int nLineSpace ) { int nBandDataSize = GDALGetDataTypeSize(eDataType) / 8; int nBufDataSize = GDALGetDataTypeSize( eBufType ) / 8; int nBytesToRW = nPixelOffset * nXSize; /* -------------------------------------------------------------------- */ /* Use direct IO without caching if: */ /* */ /* GDAL_ONE_BIG_READ is enabled */ /* */ /* or */ /* */ /* the length of a scanline on disk is more than 50000 bytes, and the */ /* width of the requested chunk is less than 40% of the whole scanline */ /* and none of the requested scanlines are already in the cache. */ /* -------------------------------------------------------------------- */ if( nPixelOffset < 0 ) { return GDALRasterBand::IRasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize, pData, nBufXSize, nBufYSize, eBufType, nPixelSpace, nLineSpace ); } if ( !CSLTestBoolean( CPLGetConfigOption( "GDAL_ONE_BIG_READ", "NO") ) ) { if ( nLineSize < 50000 || nBytesToRW > nLineSize / 5 * 2 || IsLineLoaded( nYOff, nYSize ) ) { return GDALRasterBand::IRasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize, pData, nBufXSize, nBufYSize, eBufType, nPixelSpace, nLineSpace ); } } /* ==================================================================== */ /* Read data. */ /* ==================================================================== */ if ( eRWFlag == GF_Read ) { /* -------------------------------------------------------------------- */ /* Do we have overviews that would be appropriate to satisfy */ /* this request? */ /* -------------------------------------------------------------------- */ if( (nBufXSize < nXSize || nBufYSize < nYSize) && GetOverviewCount() > 0 ) { if( OverviewRasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize, pData, nBufXSize, nBufYSize, eBufType, nPixelSpace, nLineSpace ) == CE_None ) return CE_None; } /* ==================================================================== */ /* 1. Simplest case when we should get contiguous block */ /* of uninterleaved pixels. */ /* ==================================================================== */ if ( nXSize == GetXSize() && nXSize == nBufXSize && nYSize == nBufYSize && eBufType == eDataType && nPixelOffset == nBandDataSize && nPixelSpace == nBufDataSize && nLineSpace == nPixelSpace * nXSize ) { if ( AccessBlock( nImgOffset + (vsi_l_offset)nYOff * nLineOffset + nXOff, nXSize * nYSize * nBandDataSize, pData ) != CE_None ) { CPLError( CE_Failure, CPLE_FileIO, "Failed to read %d bytes at %lu.", nXSize * nYSize * nBandDataSize, (unsigned long) (nImgOffset + (vsi_l_offset)nYOff * nLineOffset + nXOff) ); } } /* ==================================================================== */ /* 2. Case when we need deinterleave and/or subsample data. */ /* ==================================================================== */ else { GByte *pabyData; double dfSrcXInc, dfSrcYInc; int iLine; dfSrcXInc = (double)nXSize / nBufXSize; dfSrcYInc = (double)nYSize / nBufYSize; pabyData = (GByte *) CPLMalloc( nBytesToRW ); for ( iLine = 0; iLine < nBufYSize; iLine++ ) { if ( AccessBlock( nImgOffset + ((vsi_l_offset)nYOff + (int)(iLine * dfSrcYInc)) * nLineOffset + nXOff * nPixelOffset, nBytesToRW, pabyData ) != CE_None ) { CPLError( CE_Failure, CPLE_FileIO, "Failed to read %d bytes at %lu.", nBytesToRW, (unsigned long)(nImgOffset + ((vsi_l_offset)nYOff + (int)(iLine * dfSrcYInc)) * nLineOffset + nXOff * nPixelOffset) ); } /* -------------------------------------------------------------------- */ /* Copy data from disk buffer to user block buffer and subsample, */ /* if needed. */ /* -------------------------------------------------------------------- */ if ( nXSize == nBufXSize && nYSize == nBufYSize ) { GDALCopyWords( pabyData, eDataType, nPixelOffset, (GByte *)pData + iLine * nLineSpace, eBufType, nPixelSpace, nXSize ); } else { int iPixel; for ( iPixel = 0; iPixel < nBufXSize; iPixel++ ) { GDALCopyWords( pabyData + (int)(iPixel * dfSrcXInc) * nPixelOffset, eDataType, 0, (GByte *)pData + iLine * nLineSpace + iPixel * nBufDataSize, eBufType, nPixelSpace, 1 ); } } } CPLFree( pabyData ); } } /* ==================================================================== */ /* Write data. */ /* ==================================================================== */ else { int nBytesActuallyWritten; /* ==================================================================== */ /* 1. Simplest case when we should write contiguous block */ /* of uninterleaved pixels. */ /* ==================================================================== */ if ( nXSize == GetXSize() && nXSize == nBufXSize && nYSize == nBufYSize && eBufType == eDataType && nPixelOffset == nBandDataSize && nPixelSpace == nBufDataSize && nLineSpace == nPixelSpace * nXSize ) { /* -------------------------------------------------------------------- */ /* Byte swap the data buffer, if required. */ /* -------------------------------------------------------------------- */ if( !bNativeOrder && eDataType != GDT_Byte ) { if( GDALDataTypeIsComplex( eDataType ) ) { int nWordSize; nWordSize = GDALGetDataTypeSize(eDataType)/16; GDALSwapWords( pData, nWordSize, nXSize, nPixelOffset ); GDALSwapWords( ((GByte *) pData) + nWordSize, nWordSize, nXSize, nPixelOffset ); } else GDALSwapWords( pData, nBandDataSize, nXSize, nPixelOffset ); } /* -------------------------------------------------------------------- */ /* Seek to the right block. */ /* -------------------------------------------------------------------- */ if( Seek( nImgOffset + (vsi_l_offset)nYOff * nLineOffset + nXOff, SEEK_SET) == -1 ) { CPLError( CE_Failure, CPLE_FileIO, "Failed to seek to %lu to write data.\n", (unsigned long)(nImgOffset + (vsi_l_offset)nYOff * nLineOffset + nXOff) ); return CE_Failure; } /* -------------------------------------------------------------------- */ /* Write the block. */ /* -------------------------------------------------------------------- */ nBytesToRW = nXSize * nYSize * nBandDataSize; nBytesActuallyWritten = Write( pData, 1, nBytesToRW ); if( nBytesActuallyWritten < nBytesToRW ) { CPLError( CE_Failure, CPLE_FileIO, "Failed to write %d bytes to file. %d bytes written", nBytesToRW, nBytesActuallyWritten ); return CE_Failure; } /* -------------------------------------------------------------------- */ /* Byte swap (if necessary) back into machine order so the */ /* buffer is still usable for reading purposes. */ /* -------------------------------------------------------------------- */ if( !bNativeOrder && eDataType != GDT_Byte ) { if( GDALDataTypeIsComplex( eDataType ) ) { int nWordSize; nWordSize = GDALGetDataTypeSize(eDataType)/16; GDALSwapWords( pData, nWordSize, nXSize, nPixelOffset ); GDALSwapWords( ((GByte *) pData) + nWordSize, nWordSize, nXSize, nPixelOffset ); } else GDALSwapWords( pData, nBandDataSize, nXSize, nPixelOffset ); } } /* ==================================================================== */ /* 2. Case when we need deinterleave and/or subsample data. */ /* ==================================================================== */ else { GByte *pabyData; double dfSrcXInc, dfSrcYInc; vsi_l_offset nBlockOff; int iLine; dfSrcXInc = (double)nXSize / nBufXSize; dfSrcYInc = (double)nYSize / nBufYSize; pabyData = (GByte *) CPLMalloc( nBytesToRW ); for ( iLine = 0; iLine < nBufYSize; iLine++ ) { nBlockOff = nImgOffset + ((vsi_l_offset)nYOff + (int)(iLine*dfSrcYInc))*nLineOffset + nXOff * nPixelOffset; /* -------------------------------------------------------------------- */ /* If the data for this band is completely contiguous we don't */ /* have to worry about pre-reading from disk. */ /* -------------------------------------------------------------------- */ if( nPixelOffset > nBandDataSize ) AccessBlock( nBlockOff, nBytesToRW, pabyData ); /* -------------------------------------------------------------------- */ /* Copy data from user block buffer to disk buffer and subsample, */ /* if needed. */ /* -------------------------------------------------------------------- */ if ( nXSize == nBufXSize && nYSize == nBufYSize ) { GDALCopyWords( (GByte *)pData + iLine * nLineSpace, eBufType, nPixelSpace, pabyData, eDataType, nPixelOffset, nXSize ); } else { int iPixel; for ( iPixel = 0; iPixel < nBufXSize; iPixel++ ) { GDALCopyWords( (GByte *)pData+iLine*nLineSpace + iPixel * nBufDataSize, eBufType, nPixelSpace, pabyData + (int)(iPixel * dfSrcXInc) * nPixelOffset, eDataType, 0, 1 ); } } /* -------------------------------------------------------------------- */ /* Byte swap the data buffer, if required. */ /* -------------------------------------------------------------------- */ if( !bNativeOrder && eDataType != GDT_Byte ) { if( GDALDataTypeIsComplex( eDataType ) ) { int nWordSize; nWordSize = GDALGetDataTypeSize(eDataType)/16; GDALSwapWords( pabyData, nWordSize, nXSize, nPixelOffset ); GDALSwapWords( ((GByte *) pabyData) + nWordSize, nWordSize, nXSize, nPixelOffset ); } else GDALSwapWords( pabyData, nBandDataSize, nXSize, nPixelOffset ); } /* -------------------------------------------------------------------- */ /* Seek to the right line in block. */ /* -------------------------------------------------------------------- */ if( Seek( nBlockOff, SEEK_SET) == -1 ) { CPLError( CE_Failure, CPLE_FileIO, "Failed to seek to %ld to read.\n", (long)nBlockOff ); return CE_Failure; } /* -------------------------------------------------------------------- */ /* Write the line of block. */ /* -------------------------------------------------------------------- */ nBytesActuallyWritten = Write( pabyData, 1, nBytesToRW ); if( nBytesActuallyWritten < nBytesToRW ) { CPLError( CE_Failure, CPLE_FileIO, "Failed to write %d bytes to file. %d bytes written", nBytesToRW, nBytesActuallyWritten ); return CE_Failure; } /* -------------------------------------------------------------------- */ /* Byte swap (if necessary) back into machine order so the */ /* buffer is still usable for reading purposes. */ /* -------------------------------------------------------------------- */ if( !bNativeOrder && eDataType != GDT_Byte ) { if( GDALDataTypeIsComplex( eDataType ) ) { int nWordSize; nWordSize = GDALGetDataTypeSize(eDataType)/16; GDALSwapWords( pabyData, nWordSize, nXSize, nPixelOffset ); GDALSwapWords( ((GByte *) pabyData) + nWordSize, nWordSize, nXSize, nPixelOffset ); } else GDALSwapWords( pabyData, nBandDataSize, nXSize, nPixelOffset ); } } bDirty = TRUE; CPLFree( pabyData ); } } return CE_None; }
CPLErr RawRasterBand::IRasterIO( GDALRWFlag eRWFlag, int nXOff, int nYOff, int nXSize, int nYSize, void * pData, int nBufXSize, int nBufYSize, GDALDataType eBufType, int nPixelSpace, int nLineSpace ) { int nBandDataSize = GDALGetDataTypeSize(eDataType) / 8; int nBufDataSize = GDALGetDataTypeSize( eBufType ) / 8; int nBytesToRW = nPixelOffset * nXSize; if( !CanUseDirectIO(nXOff, nYOff, nXSize, nYSize, eBufType ) ) { return GDALRasterBand::IRasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize, pData, nBufXSize, nBufYSize, eBufType, nPixelSpace, nLineSpace ); } CPLDebug("RAW", "Using direct IO implementation"); /* ==================================================================== */ /* Read data. */ /* ==================================================================== */ if ( eRWFlag == GF_Read ) { /* -------------------------------------------------------------------- */ /* Do we have overviews that would be appropriate to satisfy */ /* this request? */ /* -------------------------------------------------------------------- */ if( (nBufXSize < nXSize || nBufYSize < nYSize) && GetOverviewCount() > 0 ) { if( OverviewRasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize, pData, nBufXSize, nBufYSize, eBufType, nPixelSpace, nLineSpace ) == CE_None ) return CE_None; } /* ==================================================================== */ /* 1. Simplest case when we should get contiguous block */ /* of uninterleaved pixels. */ /* ==================================================================== */ if ( nXSize == GetXSize() && nXSize == nBufXSize && nYSize == nBufYSize && eBufType == eDataType && nPixelOffset == nBandDataSize && nPixelSpace == nBufDataSize && nLineSpace == nPixelSpace * nXSize ) { vsi_l_offset nOffset = nImgOffset + (vsi_l_offset)nYOff * nLineOffset + nXOff; if ( AccessBlock( nOffset, nXSize * nYSize * nBandDataSize, pData ) != CE_None ) { CPLError( CE_Failure, CPLE_FileIO, "Failed to read %d bytes at " CPL_FRMT_GUIB ".", nXSize * nYSize * nBandDataSize, nOffset); } } /* ==================================================================== */ /* 2. Case when we need deinterleave and/or subsample data. */ /* ==================================================================== */ else { GByte *pabyData; double dfSrcXInc, dfSrcYInc; int iLine; dfSrcXInc = (double)nXSize / nBufXSize; dfSrcYInc = (double)nYSize / nBufYSize; pabyData = (GByte *) CPLMalloc( nBytesToRW ); for ( iLine = 0; iLine < nBufYSize; iLine++ ) { vsi_l_offset nOffset = nImgOffset + ((vsi_l_offset)nYOff + (vsi_l_offset)(iLine * dfSrcYInc)) * nLineOffset + nXOff * nPixelOffset; if ( AccessBlock( nOffset, nBytesToRW, pabyData ) != CE_None ) { CPLError( CE_Failure, CPLE_FileIO, "Failed to read %d bytes at " CPL_FRMT_GUIB ".", nBytesToRW, nOffset ); } /* -------------------------------------------------------------------- */ /* Copy data from disk buffer to user block buffer and subsample, */ /* if needed. */ /* -------------------------------------------------------------------- */ if ( nXSize == nBufXSize && nYSize == nBufYSize ) { GDALCopyWords( pabyData, eDataType, nPixelOffset, (GByte *)pData + (vsi_l_offset)iLine * nLineSpace, eBufType, nPixelSpace, nXSize ); } else { int iPixel; for ( iPixel = 0; iPixel < nBufXSize; iPixel++ ) { GDALCopyWords( pabyData + (vsi_l_offset)(iPixel * dfSrcXInc) * nPixelOffset, eDataType, nPixelOffset, (GByte *)pData + (vsi_l_offset)iLine * nLineSpace + (vsi_l_offset)iPixel * nPixelSpace, eBufType, nPixelSpace, 1 ); } } } CPLFree( pabyData ); } } /* ==================================================================== */ /* Write data. */ /* ==================================================================== */ else { int nBytesActuallyWritten; /* ==================================================================== */ /* 1. Simplest case when we should write contiguous block */ /* of uninterleaved pixels. */ /* ==================================================================== */ if ( nXSize == GetXSize() && nXSize == nBufXSize && nYSize == nBufYSize && eBufType == eDataType && nPixelOffset == nBandDataSize && nPixelSpace == nBufDataSize && nLineSpace == nPixelSpace * nXSize ) { /* -------------------------------------------------------------------- */ /* Byte swap the data buffer, if required. */ /* -------------------------------------------------------------------- */ if( !bNativeOrder && eDataType != GDT_Byte ) { if( GDALDataTypeIsComplex( eDataType ) ) { int nWordSize; nWordSize = GDALGetDataTypeSize(eDataType)/16; GDALSwapWords( pData, nWordSize, nXSize, nPixelOffset ); GDALSwapWords( ((GByte *) pData) + nWordSize, nWordSize, nXSize, nPixelOffset ); } else GDALSwapWords( pData, nBandDataSize, nXSize, nPixelOffset ); } /* -------------------------------------------------------------------- */ /* Seek to the right block. */ /* -------------------------------------------------------------------- */ vsi_l_offset nOffset = nImgOffset + (vsi_l_offset)nYOff * nLineOffset + nXOff; if( Seek( nOffset, SEEK_SET) == -1 ) { CPLError( CE_Failure, CPLE_FileIO, "Failed to seek to " CPL_FRMT_GUIB " to write data.\n", nOffset); return CE_Failure; } /* -------------------------------------------------------------------- */ /* Write the block. */ /* -------------------------------------------------------------------- */ nBytesToRW = nXSize * nYSize * nBandDataSize; nBytesActuallyWritten = Write( pData, 1, nBytesToRW ); if( nBytesActuallyWritten < nBytesToRW ) { CPLError( CE_Failure, CPLE_FileIO, "Failed to write %d bytes to file. %d bytes written", nBytesToRW, nBytesActuallyWritten ); return CE_Failure; } /* -------------------------------------------------------------------- */ /* Byte swap (if necessary) back into machine order so the */ /* buffer is still usable for reading purposes. */ /* -------------------------------------------------------------------- */ if( !bNativeOrder && eDataType != GDT_Byte ) { if( GDALDataTypeIsComplex( eDataType ) ) { int nWordSize; nWordSize = GDALGetDataTypeSize(eDataType)/16; GDALSwapWords( pData, nWordSize, nXSize, nPixelOffset ); GDALSwapWords( ((GByte *) pData) + nWordSize, nWordSize, nXSize, nPixelOffset ); } else GDALSwapWords( pData, nBandDataSize, nXSize, nPixelOffset ); } } /* ==================================================================== */ /* 2. Case when we need deinterleave and/or subsample data. */ /* ==================================================================== */ else { GByte *pabyData; double dfSrcXInc, dfSrcYInc; vsi_l_offset nBlockOff; int iLine; dfSrcXInc = (double)nXSize / nBufXSize; dfSrcYInc = (double)nYSize / nBufYSize; pabyData = (GByte *) CPLMalloc( nBytesToRW ); for ( iLine = 0; iLine < nBufYSize; iLine++ ) { nBlockOff = nImgOffset + ((vsi_l_offset)nYOff + (vsi_l_offset)(iLine*dfSrcYInc))*nLineOffset + nXOff * nPixelOffset; /* -------------------------------------------------------------------- */ /* If the data for this band is completely contiguous we don't */ /* have to worry about pre-reading from disk. */ /* -------------------------------------------------------------------- */ if( nPixelOffset > nBandDataSize ) AccessBlock( nBlockOff, nBytesToRW, pabyData ); /* -------------------------------------------------------------------- */ /* Copy data from user block buffer to disk buffer and subsample, */ /* if needed. */ /* -------------------------------------------------------------------- */ if ( nXSize == nBufXSize && nYSize == nBufYSize ) { GDALCopyWords( (GByte *)pData + (vsi_l_offset)iLine * nLineSpace, eBufType, nPixelSpace, pabyData, eDataType, nPixelOffset, nXSize ); } else { int iPixel; for ( iPixel = 0; iPixel < nBufXSize; iPixel++ ) { GDALCopyWords( (GByte *)pData+(vsi_l_offset)iLine*nLineSpace + (vsi_l_offset)iPixel * nPixelSpace, eBufType, nPixelSpace, pabyData + (vsi_l_offset)(iPixel * dfSrcXInc) * nPixelOffset, eDataType, nPixelOffset, 1 ); } } /* -------------------------------------------------------------------- */ /* Byte swap the data buffer, if required. */ /* -------------------------------------------------------------------- */ if( !bNativeOrder && eDataType != GDT_Byte ) { if( GDALDataTypeIsComplex( eDataType ) ) { int nWordSize; nWordSize = GDALGetDataTypeSize(eDataType)/16; GDALSwapWords( pabyData, nWordSize, nXSize, nPixelOffset ); GDALSwapWords( ((GByte *) pabyData) + nWordSize, nWordSize, nXSize, nPixelOffset ); } else GDALSwapWords( pabyData, nBandDataSize, nXSize, nPixelOffset ); } /* -------------------------------------------------------------------- */ /* Seek to the right line in block. */ /* -------------------------------------------------------------------- */ if( Seek( nBlockOff, SEEK_SET) == -1 ) { CPLError( CE_Failure, CPLE_FileIO, "Failed to seek to " CPL_FRMT_GUIB " to read.\n", nBlockOff ); return CE_Failure; } /* -------------------------------------------------------------------- */ /* Write the line of block. */ /* -------------------------------------------------------------------- */ nBytesActuallyWritten = Write( pabyData, 1, nBytesToRW ); if( nBytesActuallyWritten < nBytesToRW ) { CPLError( CE_Failure, CPLE_FileIO, "Failed to write %d bytes to file. %d bytes written", nBytesToRW, nBytesActuallyWritten ); return CE_Failure; } /* -------------------------------------------------------------------- */ /* Byte swap (if necessary) back into machine order so the */ /* buffer is still usable for reading purposes. */ /* -------------------------------------------------------------------- */ if( !bNativeOrder && eDataType != GDT_Byte ) { if( GDALDataTypeIsComplex( eDataType ) ) { int nWordSize; nWordSize = GDALGetDataTypeSize(eDataType)/16; GDALSwapWords( pabyData, nWordSize, nXSize, nPixelOffset ); GDALSwapWords( ((GByte *) pabyData) + nWordSize, nWordSize, nXSize, nPixelOffset ); } else GDALSwapWords( pabyData, nBandDataSize, nXSize, nPixelOffset ); } } bDirty = TRUE; CPLFree( pabyData ); } } return CE_None; }