Exemple #1
0
        /// <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);
        }