/// <summary>
        /// Creates a new matrix with a border of the supplied size around the supplied matrix.
        /// the resulting matrix starts at zero coordinates.
        /// </summary>
        public static Matrix <T> CopyWithBorder <T>(this Matrix <T> matrix, Border2l border)
        {
            var bm = new Matrix <T>(matrix.SX + border.Min.X + border.Max.X,
                                    matrix.SY + border.Min.Y + border.Max.Y);

            bm.SubCenter(border).Set(matrix);
            return(bm);
        }
        /// <summary>
        /// Creates a new matrix with a border of the supplied size around the supplied matrix.
        /// the resulting matrix starts at zero coordinates.
        /// </summary>
        public static Matrix <T1> MapWithBorder <T, T1>(
            this Matrix <T> matrix, Border2l border,
            Func <T, T1> item_fun)
        {
            var bm = new Matrix <T1>(matrix.SX + border.Min.X + border.Max.X,
                                     matrix.SY + border.Min.Y + border.Max.Y);

            bm.SubCenter(border).SetMap(matrix, item_fun);
            return(bm);
        }
        /// <summary>
        /// Creates a new matrix with a border of the supplied size around the supplied matrix.
        /// The resulting matrix retains the coordinates of the original matrix.
        /// </summary>
        public static Matrix <T> CopyWithBorderWindow <T>(this Matrix <T> matrix, Border2l border)
        {
            var bm = new Matrix <T>(matrix.SX + border.Min.X + border.Max.X,
                                    matrix.SY + border.Min.Y + border.Max.Y)
            {
                F = new V2l(matrix.FX - border.Min.X, matrix.FY - border.Min.Y)
            };

            bm.SubCenter(border).Set(matrix);
            return(bm);
        }
 /// <summary>
 /// Process an image volume with specific actions for the center and border
 /// parts.
 /// </summary>
 public static void ApplyCenterBordersAndCorners <Td, Tv>(
     this Matrix <Td, Tv> source, Border2l border,
     Action <Matrix <Td, Tv> > actCenter,
     Action <Matrix <Td, Tv> > actMinX, Action <Matrix <Td, Tv> > actMaxX,
     Action <Matrix <Td, Tv> > actMinY, Action <Matrix <Td, Tv> > actMaxY,
     Action <Matrix <Td, Tv> > actMinXMinY, Action <Matrix <Td, Tv> > actMaxXMinY,
     Action <Matrix <Td, Tv> > actMinXMaxY, Action <Matrix <Td, Tv> > actMaxXMaxY)
 {
     actCenter(source.SubCenter(border));
     actMinX(source.SubMinX(border)); actMaxX(source.SubMaxX(border));
     actMinY(source.SubMinY(border)); actMaxY(source.SubMaxY(border));
     actMinXMinY(source.SubMinXMinY(border)); actMaxXMinY(source.SubMaxXMinY(border));
     actMinXMaxY(source.SubMinXMaxY(border)); actMaxXMaxY(source.SubMaxXMaxY(border));
 }
        /// <summary>
        /// Process an image volume with specific actions for the center and border
        /// parts.
        /// </summary>
        public static Matrix <T1> ProcessCenterBordersAndCorners <T, T1>(
            this Matrix <T> source, Border2l border,
            Action <Matrix <T>, Matrix <T1> > actCenter,
            Action <Matrix <T>, Matrix <T1> > actMinX, Action <Matrix <T>, Matrix <T1> > actMaxX,
            Action <Matrix <T>, Matrix <T1> > actMinY, Action <Matrix <T>, Matrix <T1> > actMaxY,
            Action <Matrix <T>, Matrix <T1> > actMinXMinY, Action <Matrix <T>, Matrix <T1> > actMaxXMinY,
            Action <Matrix <T>, Matrix <T1> > actMinXMaxY, Action <Matrix <T>, Matrix <T1> > actMaxXMaxY)
        {
            var target = new Matrix <T1>(source.Size);

            target.F = source.F;

            actCenter(source.SubCenter(border), target.SubCenter(border));
            actMinX(source.SubMinX(border), target.SubMinX(border));
            actMaxX(source.SubMaxX(border), target.SubMaxX(border));
            actMinY(source.SubMinY(border), target.SubMinY(border));
            actMaxY(source.SubMaxY(border), target.SubMaxY(border));
            actMinXMinY(source.SubMinXMinY(border), target.SubMinXMinY(border));
            actMaxXMinY(source.SubMaxXMinY(border), target.SubMaxXMinY(border));
            actMinXMaxY(source.SubMinXMaxY(border), target.SubMinXMaxY(border));
            actMaxXMaxY(source.SubMaxXMaxY(border), target.SubMaxXMaxY(border));

            return(target);
        }