/// <summary> /// This creates a window from this raster. The window will still save to the same /// source file, but only has access to a small window of data, so it can be loaded like a buffer. /// The georeferenced extents will be for the new window, not the original raster. startRow and endRow /// will exist in the new raster, however, so that it knows how to copy values back to the original raster. /// </summary> /// <param name="startRow">The 0 based integer index of the top row to get from this raster. If this raster is itself a window, 0 represents the startRow from the file.</param> /// <param name="endRow">The integer index of the bottom row to get from this raster. The largest allowed value is NumRows - 1.</param> /// <param name="startColumn">The 0 based integer index of the leftmost column to get from this raster. If this raster is a window, 0 represents the startColumn from the file.</param> /// <param name="endColumn">The 0 based integer index of the rightmost column to get from this raster. The largest allowed value is NumColumns - 1</param> /// <param name="inRam">Boolean. If this is true and the window is small enough, a copy of the values will be loaded into memory.</param> /// <returns>An implementation of IRaster</returns> public new IRaster GetWindow(int startRow, int endRow, int startColumn, int endColumn, bool inRam) { int numCols = endColumn - startColumn + 1; int numRows = endRow - startRow + 1; var result = new BinaryRaster <T>(); result.Filename = Filename; result.Projection = Projection; result.DataType = typeof(int); result.NumRows = endRow - startRow + 1; result.NumColumns = endColumn - startColumn + 1; result.NumRowsInFile = NumRowsInFile; result.NumColumnsInFile = NumColumnsInFile; result.NoDataValue = NoDataValue; result.StartColumn = startColumn + StartColumn; result.StartRow = startRow + StartRow; result.EndColumn = endColumn + StartColumn; result.EndRow = EndRow + StartRow; // Reposition the "raster" so that it matches the window, not the whole raster // X = [0] + [1] * column + [2] * row; // Y = [3] + [4] * column + [5] * row; result.Bounds = new RasterBounds(result.NumRows, result.NumColumns, new double[6]); result.Bounds.AffineCoefficients[0] = Bounds.AffineCoefficients[0] + Bounds.AffineCoefficients[1] * startColumn + Bounds.AffineCoefficients[2] * startRow; result.Bounds.AffineCoefficients[1] = Bounds.AffineCoefficients[1]; result.Bounds.AffineCoefficients[2] = Bounds.AffineCoefficients[2]; result.Bounds.AffineCoefficients[3] = Bounds.AffineCoefficients[3] + Bounds.AffineCoefficients[4] * startColumn + Bounds.AffineCoefficients[5] * startRow; result.Bounds.AffineCoefficients[4] = Bounds.AffineCoefficients[4]; result.Bounds.AffineCoefficients[5] = Bounds.AffineCoefficients[5]; // Now we can copy any values currently in memory. if (IsInRam) { //result.ReadHeader(Filename); result.Data = new T[numRows][]; ProgressMeter pm = new ProgressMeter(ProgressHandler, DataStrings.CopyingValues, endRow); pm.StartValue = startRow; // copy values directly using both data structures for (int row = 0; row < numRows; row++) { result.Data[row] = new T[numCols]; for (int col = 0; col < numCols; col++) { result.Data[row][col] = Data[startRow + row][startColumn + col]; } pm.CurrentValue = row; } pm.Reset(); } else { result.OpenWindow(Filename, startRow, endRow, startColumn, endColumn, inRam); } result.Value = new ValueGrid <T>(result); return(result); }
/// <summary> /// This creates a window from this raster. The window will still save to the same /// source file, but only has access to a small window of data, so it can be loaded like a buffer. /// The georeferenced extents will be for the new window, not the original raster. startRow and endRow /// will exist in the new raster, however, so that it knows how to copy values back to the original raster. /// </summary> /// <param name="startRow">The 0 based integer index of the top row to get from this raster. If this raster is itself a window, 0 represents the startRow from the file.</param> /// <param name="endRow">The integer index of the bottom row to get from this raster. The largest allowed value is NumRows - 1.</param> /// <param name="startColumn">The 0 based integer index of the leftmost column to get from this raster. If this raster is a window, 0 represents the startColumn from the file.</param> /// <param name="endColumn">The 0 based integer index of the rightmost column to get from this raster. The largest allowed value is NumColumns - 1</param> /// <param name="inRam">Boolean. If this is true and the window is small enough, a copy of the values will be loaded into memory.</param> /// <returns>An implementation of IRaster</returns> public new IRaster GetWindow(int startRow, int endRow, int startColumn, int endColumn, bool inRam) { int numCols = endColumn - startColumn + 1; int numRows = endRow - startRow + 1; var result = new BinaryRaster <T> { Filename = Filename, Projection = Projection, DataType = typeof(int), NumRows = endRow - startRow + 1, NumColumns = endColumn - startColumn + 1, NumRowsInFile = NumRowsInFile, NumColumnsInFile = NumColumnsInFile, NoDataValue = NoDataValue, StartColumn = startColumn + StartColumn, StartRow = startRow + StartRow, EndColumn = endColumn + StartColumn, EndRow = EndRow + StartRow }; // Reposition the "raster" so that it matches the window, not the whole raster var ac = new AffineTransform(Bounds.AffineCoefficients).TransfromToCorner(startColumn, startRow); result.Bounds = new RasterBounds(result.NumRows, result.NumColumns, ac); // Now we can copy any values currently in memory. if (IsInRam) { //result.ReadHeader(Filename); result.Data = new T[numRows][]; ProgressMeter pm = new ProgressMeter(ProgressHandler, DataStrings.CopyingValues, endRow) { StartValue = startRow }; // copy values directly using both data structures for (int row = 0; row < numRows; row++) { result.Data[row] = new T[numCols]; for (int col = 0; col < numCols; col++) { result.Data[row][col] = Data[startRow + row][startColumn + col]; } pm.CurrentValue = row; } pm.Reset(); } else { result.OpenWindow(Filename, startRow, endRow, startColumn, endColumn, inRam); } result.Value = new ValueGrid <T>(result); return(result); }
/// <summary> /// This creates a completely new raster from the windowed domain on the original raster. This new raster /// will have a separate source file, and values like NumRowsInFile will correspond to the newly created file. /// All the values will be copied to the new source file. If inRam = true and the new raster is small enough, /// the raster values will be loaded into memory. /// </summary> /// <param name="fileName"></param> /// <param name="startRow">The 0 based integer index of the top row to copy from this raster. If this raster is itself a window, 0 represents the startRow from the file.</param> /// <param name="endRow">The integer index of the bottom row to copy from this raster. The largest allowed value is NumRows - 1.</param> /// <param name="startColumn">The 0 based integer index of the leftmost column to copy from this raster. If this raster is a window, 0 represents the startColumn from the file.</param> /// <param name="endColumn">The 0 based integer index of the rightmost column to copy from this raster. The largest allowed value is NumColumns - 1</param> /// <param name="copyValues">If this is true, the values are saved to the file. If this is false and the data can be loaded into Ram, no file handling is done. Otherwise, a file of NoData values is created.</param> /// <param name="inRam">Boolean. If this is true and the window is small enough, a copy of the values will be loaded into memory.</param> /// <returns>An implementation of IRaster</returns> public new IRaster CopyWindow(string fileName, int startRow, int endRow, int startColumn, int endColumn, bool copyValues, bool inRam) { int numCols = endColumn - startColumn + 1; int numRows = endRow - startRow + 1; var result = new BinaryRaster <T>(fileName, numCols, numRows, inRam) { Projection = Projection }; // The affine coefficients defining the world file are the same except that they are translated over. Only the position of the // upper left corner changes. Everything else is the same as the previous raster. var ac = new AffineTransform(Bounds.AffineCoefficients).TransfromToCorner(startColumn, startRow); result.Bounds = new RasterBounds(result.NumRows, result.NumColumns, ac); if (IsInRam) { ProgressMeter pm = new ProgressMeter(ProgressHandler, DataStrings.CopyingValues, numRows); // copy values directly using both data structures for (int row = 0; row < numRows; row++) { for (int col = 0; col < numCols; col++) { result.Data[row][col] = Data[startRow + row][startColumn + col]; } pm.CurrentValue = row; } pm.Reset(); if (result.IsInRam == false) { // Force the result raster to write itself to a file and then purge its memory. result.Write(fileName); result.Data = null; } } else { if (result.IsInRam) { // the source is not in memory, so we just read the values from the file as if opening it directly from the file. result.OpenWindow(Filename, startRow, endRow, startColumn, endColumn, true); } else { // Both sources are file based so we basically copy rows of bytes from one to the other. FileStream source = new FileStream(Filename, FileMode.Open, FileAccess.Read, FileShare.Read); result.WriteHeader(fileName); FileStream dest = new FileStream(fileName, FileMode.Append, FileAccess.Write, FileShare.None); source.Seek(HeaderSize, SeekOrigin.Begin); BinaryReader bReader = new BinaryReader(source); BinaryWriter bWriter = new BinaryWriter(dest); ProgressMeter pm = new ProgressMeter(ProgressHandler, DataStrings.CopyingValues, numRows); // copy values directly using both data structures source.Seek(NumColumnsInFile * startRow * ByteSize, SeekOrigin.Current); for (int row = 0; row < numRows; row++) { source.Seek(numCols * ByteSize, SeekOrigin.Current); byte[] rowData = bReader.ReadBytes(ByteSize * numCols); bWriter.Write(rowData); source.Seek(NumColumnsInFile - endColumn + 1, SeekOrigin.Current); bWriter.Flush(); pm.CurrentValue = row; } pm.Reset(); } } return(result); }