Пример #1
0
        private LayerViewModel CreateLayerViewModel(Dataset dataSet, Band rasterBand, int stride, IntPtr data, CreateLayerViewModel layer)
        {
            WriteableBitmap bandImage = new WriteableBitmap(rasterBand.XSize, rasterBand.YSize, 96, 96, rasterBand.DataType.ToPixelFormat(), null);

            bandImage.Lock();

            int backBufferStride = bandImage.BackBufferStride;

            unsafe
            {
                if (stride == backBufferStride)
                {
                    Buffer.MemoryCopy(data.ToPointer(), bandImage.BackBuffer.ToPointer(), stride * rasterBand.YSize, stride * rasterBand.YSize);
                }
                else
                {
                    if (rasterBand.DataType == DataType.GDT_UInt16)
                    {
                        ushort *sourcePtr = (ushort *)data.ToPointer();
                        ushort *destPtr   = (ushort *)bandImage.BackBuffer.ToPointer();
                        for (int scanLine = 0; scanLine < rasterBand.YSize; ++scanLine)
                        {
                            ushort *source = sourcePtr + scanLine * stride / 2;
                            ushort *dest   = destPtr + scanLine * backBufferStride / 2;

                            Buffer.MemoryCopy(source, dest, stride, stride);
                        }
                    }
                    else
                    {
                        throw new NotSupportedException();
                    }
                }
            }

            bandImage.AddDirtyRect(new Int32Rect(0, 0, rasterBand.XSize, rasterBand.YSize));
            bandImage.Unlock();

            // Position
            double[] bandTransform = new double[6];
            dataSet.GetGeoTransform(bandTransform);
            var vecBuilder  = Vector <double> .Build;
            var upperLeft   = vecBuilder.DenseOfArray(new[] { bandTransform[0], bandTransform[3], 1 });
            var xRes        = bandTransform[1];
            var yRes        = bandTransform[5];
            var bottomRight = vecBuilder.DenseOfArray(new[] { upperLeft[0] + (rasterBand.XSize * xRes), upperLeft[1] + (rasterBand.YSize * yRes), 1 });

            double[,] matArray =
            {
                { bandTransform[1], bandTransform[2], bandTransform[0] },
                { bandTransform[4], bandTransform[5], bandTransform[3] },
                {                0,                0,                1 }
            };

            var builder      = Matrix <double> .Build;
            var transformMat = builder.DenseOfArray(matArray);

            var imageBandViewModel = new LayerViewModel(
                layer.GetName(), layer.SatelliteType, layer.Path, layer.ContrastEnhancement, xRes, yRes, bandImage, transformMat, upperLeft,
                bottomRight, layer.MinCutOff, layer.MaxCutOff, layer.R, layer.G, layer.B, false, true, true);

            return(imageBandViewModel);
        }
Пример #2
0
        /// <summary>
        /// Adds the bands from the bands view model.
        /// </summary>
        /// <param name="viewModel"></param>
        public void AddBands(AddLayersDialogViewModel viewModel, IProgress <double> progress)
        {
            // Initialize RGB data
            byte[]  bgra       = null;
            Dataset rgbDataSet = null;

            if (viewModel.AddRgb)
            {
                var firstRgbBand = viewModel.Layers.First(b => b.B || b.G || b.R);
                rgbDataSet = Gdal.Open(firstRgbBand.Path, Access.GA_ReadOnly);
                bgra       = new byte[rgbDataSet.RasterXSize * rgbDataSet.RasterYSize * 4];
            }

            var firstBand    = viewModel.Layers.First();
            var firstDataSet = Gdal.Open(firstBand.Path, Access.GA_ReadOnly);

            var builder = Matrix <double> .Build;

            int totalBands      = viewModel.Layers.Count + (viewModel.AddRgb ? 1 : 0);
            int currentProgress = 0;

            // Parallel band loading
            Parallel.ForEach(viewModel.Layers, (currentLayer, _, bandIndex) =>
            {
                // Load raster
                var dataSet    = Gdal.Open(currentLayer.Path, Access.GA_ReadOnly);
                var rasterBand = dataSet.GetRasterBand(1);

                var bitsPerPixel = rasterBand.DataType.ToPixelFormat().BitsPerPixel;

                int stride = (rasterBand.XSize * bitsPerPixel / 8);

                IntPtr data = Marshal.AllocHGlobal(stride * rasterBand.YSize);

                rasterBand.ReadRaster(0, 0, rasterBand.XSize, rasterBand.YSize, data, rasterBand.XSize, rasterBand.YSize, rasterBand.DataType, bitsPerPixel / 8, stride);

                // Cutoff
                int minCutValue, maxCutValue;
                CalculateMinMaxCut(rasterBand, currentLayer.MinCutOff, currentLayer.MaxCutOff, out minCutValue, out maxCutValue);

                // Apply RGB contrast enhancement
                if (viewModel.AddRgb && viewModel.RgbContrastEnhancement && (currentLayer.B || currentLayer.G || currentLayer.R))
                {
                    int colorOffset = currentLayer.B ? 0 : currentLayer.G ? 1 : currentLayer.R ? 2 : -1;
                    unsafe
                    {
                        // TODO what if layer is not of type uint?
                        ushort *dataPtr = (ushort *)data.ToPointer();
                        Parallel.ForEach(Partitioner.Create(0, rasterBand.XSize * rasterBand.YSize),
                                         (range) =>
                        {
                            for (int dataIndex = range.Item1; dataIndex < range.Item2; ++dataIndex)
                            {
                                ushort current = *(dataPtr + dataIndex);
                                byte val       = (byte)MoreMath.Clamp((current - minCutValue) / (double)(maxCutValue - minCutValue) * byte.MaxValue, 0, byte.MaxValue - 1);

                                bgra[dataIndex * 4 + colorOffset] = val;
                                bgra[dataIndex * 4 + 3]           = 255;
                            }
                        });
                    }
                }

                // Apply band contrast enhancement
                if (currentLayer.ContrastEnhancement)
                {
                    data = ApplyContrastEnhancement(rasterBand, data, minCutValue, maxCutValue);
                }


                Application.Current.Dispatcher.Invoke(() =>
                {
                    var imageBandViewModel = CreateLayerViewModel(dataSet, rasterBand, stride, data, currentLayer);


                    Layers.AddSorted(imageBandViewModel, Comparer <LayerViewModel> .Create((a, b) => string.Compare(a.Name, b.Name, StringComparison.Ordinal)));
                    progress.Report(++currentProgress);

                    Marshal.FreeHGlobal(data);
                });
            });

            // Load rgb image
            if (viewModel.AddRgb)
            {
                // Create RGB image
                Application.Current.Dispatcher.Invoke(() =>
                {
                    var rgbStride = rgbDataSet.RasterXSize * 4;

                    var rgbImage = BitmapSource.Create(rgbDataSet.RasterXSize, rgbDataSet.RasterYSize, 96, 96, PixelFormats.Bgra32, null, bgra, rgbStride);

                    // Transformation
                    double[] rgbTransform = new double[6];
                    rgbDataSet.GetGeoTransform(rgbTransform);
                    var vecBuilder  = Vector <double> .Build;
                    var upperLeft   = vecBuilder.DenseOfArray(new[] { rgbTransform[0], rgbTransform[3], 1 });
                    var xRes        = rgbTransform[1];
                    var yRes        = rgbTransform[5];
                    var bottomRight =
                        vecBuilder.DenseOfArray(new[]
                    {
                        upperLeft[0] + (rgbDataSet.RasterXSize * xRes),
                        upperLeft[1] + (rgbDataSet.RasterYSize * yRes), 1
                    });


                    double[,] matArray =
                    {
                        { rgbTransform[1], rgbTransform[2], rgbTransform[0] },
                        { rgbTransform[4], rgbTransform[5], rgbTransform[3] },
                        {               0,               0,               1 }
                    };

                    var transformMat = builder.DenseOfArray(matArray);

                    var layerViewModel = new LayerViewModel("RGB", SatelliteType.None, null, viewModel.RgbContrastEnhancement, xRes, yRes, new WriteableBitmap(rgbImage),
                                                            transformMat, upperLeft, bottomRight, 0, 0, false, false, false, true, false, false);

                    Layers.Insert(0, layerViewModel);

                    progress.Report(++currentProgress);
                });
            }

            // TODO use projection to get correct transformation?
            double[] transform = new double[6];
            firstDataSet.GetGeoTransform(transform);
            double[,] transformArray =
            {
                {            1, transform[2], transform[0] },
                { transform[4],           -1, transform[3] },
                {            0,            0,            1 }
            };

            Messenger.Default.Send(builder.DenseOfArray(transformArray));

            WindowEnabled = true;
        }