예제 #1
0
        private async Task <byte[]> CreateMapImageAsync(
            int width,
            int height,
            Models.Bounds boundingBox,
            string mediaType,
            bool isTransparent,
            uint backgroundColor,
            IList <string> layerNames)
        {
            var imageInfo = new SKImageInfo(
                width: width,
                height: height,
                colorType: SKColorType.Rgba8888,
                alphaType: SKAlphaType.Premul);

            using var surface = SKSurface.Create(imageInfo);
            using var canvas  = surface.Canvas;
            canvas.Clear(new SKColor(backgroundColor));

            foreach (var layerName in layerNames)
            {
                if (this.tileSourceFabric.Contains(layerName))
                {
                    await WmsHelper.DrawLayerAsync( // TODO: ? pass required format to avoid conversions
                        this.tileSourceFabric.Get(layerName),
                        width,
                        height,
                        boundingBox,
                        canvas,
                        isTransparent,
                        backgroundColor);
                }
            }

            using SKImage image = surface.Snapshot();

            if (String.Compare(mediaType, MediaTypeNames.Image.Tiff, StringComparison.OrdinalIgnoreCase) == 0)
            {
                using var bitmap = SKBitmap.FromImage(image);
                // TODO: improve performance of pixels processing, maybe using unsafe/pointers
                var pixels = bitmap.Pixels.SelectMany(p => new byte[] { p.Red, p.Green, p.Blue, p.Alpha }).ToArray();
                var tiff   = ImageHelper.CreateTiffImage(pixels, image.Width, image.Height);
                return(tiff);
            }
            else
            {
                var imageFormat = U.ImageHelper.SKEncodedImageFormatFromMediaType(mediaType);
                using SKData data = image.Encode(imageFormat, 90); // TODO: ? quality parameter
                return(data.ToArray());
            }
        }
예제 #2
0
        public async Task <IActionResult> ProcessWmsRequestAsync(
            string service = Identifiers.Wms,
            string version = Identifiers.Version111,
            string?request = null,
            string?layers  = null,
            ////string styles = null,
            string?srs    = null, // WMS version 1.1.1
            string?crs    = null, // WMS version 1.3.0
            string?bbox   = null,
            int width     = 0,
            int height    = 0,
            string?format = null,
            // Optional GetMap request parameters
            bool?transparent  = false,
            string bgcolor    = Identifiers.DefaultBackgroundColor,
            string exceptions = MediaTypeNames.Application.OgcServiceExceptionXml
            ////string time = null,
            ////string sld = null,
            ////string sld_body = null,
            // GetFeatureInfo request parameters
            ////string query_layers = null,
            ////string info_format = MediaTypeNames.Text.Plain,
            ////int x = 0,
            ////int y = 0,
            ////int i = 0, // WMS version 1.3.0
            ////int j = 0, // WMS version 1.3.0
            ////int feature_count = 1
            )
        {
            //// $"WMS [{Request.GetOwinContext().Request.RemoteIpAddress}:{Request.GetOwinContext().Request.RemotePort}] {Request.RequestUri}";

            if (String.Compare(service, Identifiers.Wms, StringComparison.OrdinalIgnoreCase) != 0)
            {
                var message = $"Unknown service: '{service}' (should be '{Identifiers.Wms}')";
                return(ResponseWithExceptionReport(Identifiers.InvalidParameterValue, message, "service"));
            }

            if ((String.Compare(version, Identifiers.Version111, StringComparison.Ordinal) != 0) &&
                (String.Compare(version, Identifiers.Version130, StringComparison.Ordinal) != 0))
            {
                var message = $"Unsupported {nameof(version)}: {version} (should be one of: {Identifiers.Version111}, {Identifiers.Version130})";
                return(ResponseWithExceptionReport(Identifiers.InvalidParameterValue, message, "version"));
            }

            if ((String.Compare(exceptions, MediaTypeNames.Application.OgcServiceExceptionXml, StringComparison.Ordinal) != 0) &&
                (String.Compare(exceptions, "XML", StringComparison.Ordinal) != 0))
            {
                var message = $"Unsupported {nameof(exceptions)}: {exceptions} (should be {MediaTypeNames.Application.OgcServiceExceptionXml})";
                return(ResponseWithExceptionReport(Identifiers.InvalidParameterValue, message, "exceptions"));
            }

            if (String.Compare(request, Identifiers.GetCapabilities, StringComparison.Ordinal) == 0)
            {
                return(this.ProcessGetCapabilitiesRequest(WmsHelper.GetWmsVersion(version)));
            }
            else if (String.Compare(request, Identifiers.GetMap, StringComparison.Ordinal) == 0)
            {
                return(await this.ProcessGetMapRequestAsync(
                           version,
                           layers,
                           WmsHelper.GetWmsVersion(version) == Wms.Version.Version130?crs : srs,
                           bbox,
                           width,
                           height,
                           format,
                           transparent,
                           bgcolor));
            }
            ////else if (String.Compare(request, Identifiers.GetFeatureInfo, StringComparison.Ordinal) == 0)
            ////{
            ////return await this.ProcessGetFeatureInfoRequestAsync(
            ////    bbox, width,
            ////    query_layers, info_format,
            ////    v == Wms.Version.v130 ? i : x,
            ////    v == Wms.Version.v130 ? j : y,
            ////    feature_count);
            ////}
            else
            {
                var message = $"Unsupported request: '{request}' ({Identifiers.GetCapabilities}, {Identifiers.GetMap}, {Identifiers.GetFeatureInfo})";
                return(ResponseWithServiceExceptionReport(Identifiers.OperationNotSupported, message, version));
            }
        }
예제 #3
0
        private async Task <IActionResult> ProcessGetMapRequestAsync(
            string version,
            string?layers,
            string?srs,
            string?bbox,
            int width,
            int height,
            string?format,
            bool?transparent,
            string bgcolor)
        {
            // TODO: config ?
            const int MinSize = 1;
            const int MaxSize = 32768;

            if (String.IsNullOrEmpty(format))
            {
                var message = "No map output format was specified";
                return(ResponseWithServiceExceptionReport(Identifiers.InvalidFormat, message, version));
            }

            // TODO: more output formats
            var isFormatSupported = U.EntitiesConverter.IsFormatInList(
                new[]
            {
                MediaTypeNames.Image.Png,
                MediaTypeNames.Image.Jpeg,
                MediaTypeNames.Image.Tiff,
            },
                format);

            if (!isFormatSupported)
            {
                var message = $"Image output format '{format}' is not supported";
                return(ResponseWithServiceExceptionReport(Identifiers.InvalidFormat, message, version));
            }

            if (String.IsNullOrEmpty(layers))
            {
                var message = "GetMap request must include a valid LAYERS parameter.";
                return(ResponseWithServiceExceptionReport(Identifiers.LayerNotDefined, message, version));
            }

            if ((width < MinSize) ||
                (width > MaxSize) ||
                (height < MinSize) ||
                (height > MaxSize))
            {
                var message = $"Missing or invalid requested map size. Parameters WIDTH and HEIGHT must present and be positive integers (got WIDTH={width}, HEIGHT={height}).";
                return(ResponseWithServiceExceptionReport(Identifiers.MissingOrInvalidParameter, message, version));
            }

            if (String.IsNullOrEmpty(srs))
            {
                var message = $"GetMap request must include a valid {(WmsHelper.GetWmsVersion(version) == Wms.Version.Version130 ? "CRS" : "SRS")} parameter.";
                return(ResponseWithServiceExceptionReport(Identifiers.MissingBBox, message, version));
            }

            // TODO: EPSG:4326 output support
            if (String.Compare(srs, Identifiers.EPSG3857, StringComparison.OrdinalIgnoreCase) != 0)
            {
                var message = $"SRS '{srs}' is not supported, only {Identifiers.EPSG3857} is currently supported.";
                return(ResponseWithServiceExceptionReport(Identifiers.InvalidSRS, message, version));
            }

            if (bbox == null)
            {
                var message = "GetMap request must include a valid BBOX parameter.";
                return(ResponseWithServiceExceptionReport(Identifiers.MissingBBox, message, version));
            }

            var boundingBox = Models.Bounds.FromCommaSeparatedString(bbox);

            if (boundingBox == null)
            {
                var message = $"GetMap request must include a valid BBOX parameter with 4 coordinates (got '{bbox}').";
                return(ResponseWithServiceExceptionReport(null, message, version));
            }

            if (boundingBox.Right <= boundingBox.Left || boundingBox.Top <= boundingBox.Bottom)
            {
                var message = $"GetMap request must include a valid BBOX parameter with minX < maxX and minY < maxY coordinates (got '{bbox}').";
                return(ResponseWithServiceExceptionReport(null, message, version));
            }

            var layersList = layers.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);

            var isTransparent   = transparent ?? false;
            var backgroundColor = U.EntitiesConverter.GetArgbColorFromString(bgcolor, isTransparent);
            var imageData       = await this.CreateMapImageAsync(width, height, boundingBox, format, isTransparent, backgroundColor, layersList);

            return(File(imageData, format));
        }