ImageWMSServer.py 10.0 KB
# coding=utf-8
#author:        4N
#createtime:    2021/10/26
#email:         nheweijun@sina.com


import numpy
from app.util.component.ParameterUtil import ParameterUtil
from .Cache import Cache
from app.modules.service.models import ImageService
from flask import Response
from .ImageData import ImageData
from .MyThread import MyThread
from .Opencv import Opencv
import json
import random
import configure
import threading
from .ImageServer import ImageServer


class ImageWMSServer(ImageServer):

    _instance_lock = threading.Lock()
    singleton = None

    def __init__(self):
        pass

    def __new__(cls, *args, **kwargs):
        if not cls.singleton:
            with ImageWMSServer._instance_lock:
                cls.singleton = super().__new__(cls)
        return cls.singleton

    def wms(self,service_name,parameter,type="name"):

        # 获取缓存信息
        image_service_info, zoo, servers = Cache.cache_data(service_name, type=type)
        # 转换参数
        parameter = ParameterUtil.to_lower(parameter)
        re = parameter.get("request")
        if re and re.__eq__("GetCapabilities"):
            return self.get_wms_capabilities(image_service_info["service"])

        bbox = parameter.get("bbox")
        width = int(parameter.get("width")) if parameter.get("width") else 256
        height = int(parameter.get("height")) if parameter.get("height") else 256
        image_type = parameter.get("format") if parameter.get("format") else "image/png"
        quality = int(parameter.get("quality")) if parameter.get("quality") else 30

        extent = [float(x) for x in bbox.split(",")]

        intersect_image = [im for im in image_service_info["images"] if
                           self.determin_intersect(json.loads(im.extent), extent)]

        if len(intersect_image) > 1:

            # 结果矩阵
            empty_list = [numpy.zeros((height, width), dtype=int) + 65536,
                          numpy.zeros((height, width), dtype=int) + 65536,
                          numpy.zeros((height, width), dtype=int) + 65536]

            pixel_array = numpy.zeros((height, width, 3), dtype=int)
            thread_list = []

            for image in intersect_image:
                # 该影像的服务器,随机选取一个
                image_servers = image.server.split(",")
                image_servers = [ser for ser in image_servers if ser in servers]
                if len(image_servers) > 0:
                    indx = int(random.random() * len(image_servers))
                    image_server = image_servers[indx]
                else:
                    image_server = "None"
                bands = json.loads(image.band_view)

                image_data = ImageData(image_server, image)

                thread: MyThread = MyThread(image_data.get_data, args=(extent, bands, height, width))
                thread.start()
                thread_list.append(thread)

            for thread in thread_list:
                thread.join()
                data = thread.get_result()

                # 掩膜在中央接口生成,合图
                mask = numpy.zeros((height, width), dtype=int)
                mask2 = numpy.zeros((height, width), dtype=int)
                jizhun = data[:, :, 0]
                mask[jizhun == 65536] = 1
                mask[jizhun != 65536] = 0
                mask2[jizhun == 65536] = 0
                mask2[jizhun != 65536] = 1
                # 掩膜计算
                for i, d in enumerate(empty_list):
                    empty_list[i] = empty_list[i] * mask + data[:, :, i] * mask2

            for ii in [0, 1, 2]:
                # opencv 颜色排序为GBR
                pixel_array[:, :, 2 - ii] = empty_list[ii]


        elif len(intersect_image) == 1:
            # 该影像的服务器,随机选取一个
            image = intersect_image[0]
            image_servers = image.server.split(",")
            image_servers = [ser for ser in image_servers if ser in servers]
            if len(image_servers) > 0:
                indx = int(random.random() * len(image_servers))
                image_server = image_servers[indx]
            else:
                image_server = "None"

            bands = json.loads(image.band_view)

            image_data = ImageData(image_server, image)

            pixel_array_t = image_data.get_data(extent, bands, height, width)

            pixel_array = numpy.zeros((height, width, 3), dtype=int)
            for ii in [0, 1, 2]:
                # opencv 颜色排序为GBR
                pixel_array[:, :, 2 - ii] = pixel_array_t[:, :, ii]
        else:
            # 结果矩阵
            pixel_array = numpy.zeros((height, width, 3), dtype=int) + 65536

        # 将图片生成在内存中,然后直接返回response
        im_data = Opencv.create_image(image_type, pixel_array, quality)

        if parameter.get("overview"):
            return pixel_array
        return Response(im_data, mimetype=image_type.lower())


    def get_wms_capabilities(self, image_service: ImageService):

        xml = '''<?xml version="1.0" encoding="utf-8" ?>
        <WMS_Capabilities version="1.2.0">
            <Service>
                <Name>WMS</Name>
                <Title>{service_title}</Title>
                <Abstract>{abstract}</Abstract>
                <Keywords>GIMS</Keywords>
                <OnlineResource/>
                <Fees>none</Fees>
                <AccessConstraints>none</AccessConstraints>
            </Service>
            <Capability>
                <Request>
                    <GetCapabilities>
                        <Format>text/xml</Format>
                        <DCPType>
                            <HTTP>
                                <Get>
                                    <OnlineResource xlink:href="{url}" xlink:type="simple" xmlns:xlink="http://www.w3.org/1999/xlink"/>
                                </Get>
                            </HTTP>
                        </DCPType>
                    </GetCapabilities>
                    <GetMap>
                        <Format>png</Format>
                        <Format>jpeg</Format>
                        <Format>gif</Format>
                        <Format>image/png</Format>
                        <Format>image/jpeg</Format>
                        <Format>image/gif</Format>
                        <DCPType>
                            <HTTP>
                                <Get>
                                    <OnlineResource xlink:href="{url}" xlink:type="simple" xmlns:xlink="http://www.w3.org/1999/xlink"/>
                                </Get>
                            </HTTP>
                        </DCPType>
                    </GetMap>
                    <Map>
                        <Format>
                            <PNG/>
                            <GIF/>
                            <JPG/>
                        </Format>
                        <DCPType>
                            <HTTP>
                                <Get onlineResource="{url}"/>
                            </HTTP>
                        </DCPType>
                    </Map>
                    <Capabilities>
                        <Format>
                            <WMS_XML/>
                        </Format>
                        <DCPType>
                            <HTTP>
                                <Get onlineResource="{url}"/>
                            </HTTP>
                        </DCPType>
                    </Capabilities>
                    <FeatureInfo>
                        <Format>
                            <XML/>
                            <MIME/>
                        </Format>
                        <DCPType>
                            <HTTP>
                                <Get onlineResource="{url}"/>
                            </HTTP>
                        </DCPType>
                    </FeatureInfo>
                </Request>
                <Exception>
                    <Format>
                        <WMS_XML/>
                        <INIMAGE/>
                        <BLANK/>
                    </Format>
                </Exception>
                <Layer>
                    <Name>{service_name}</Name>
                    <Title>{service_title}</Title>
                    <CRS>{crs}</CRS>
                    <BoundingBox CRS="{crs}" maxx="{maxx}" maxy="{maxy}" minx="{minx}" miny="{miny}"/>

                    <Layer queryable="1">
                        <CRS>{crs}</CRS>
                        <Name>{layer_name}</Name>
                        <Title>{layer_title}</Title>
                        <BoundingBox CRS="{crs}" maxx="{maxx}" maxy="{maxy}" minx="{minx}" miny="{miny}"/>
                    </Layer>
                </Layer>
            </Capability>
        </WMS_Capabilities>'''

        extent = json.loads(image_service.extent)
        xml = xml.format(service_title=image_service.name,
                         service_name=image_service.name,
                         abstract="None",
                         crs="ESPG:4326",
                         layer_name=image_service.name,
                         layer_title=image_service.name,
                         maxx=extent[2],
                         maxy=extent[3],
                         minx=extent[0],
                         miny=extent[1],
                         url="http://{}/API/Service/Image/WMS?guid={}".format(configure.deploy_ip_host,
                                                                              image_service.guid))

        r = Response(response=xml, status=200, mimetype="application/xml")
        r.headers["Content-Type"] = "text/xml; charset=utf-8"
        return r

    def determin_intersect(self, extent1, extent2):
        if extent2[2] < extent1[0] or extent2[0] > extent1[2] or extent2[1] > extent1[
            3] or extent2[3] < extent1[1]:
            return False
        else:
            return True