Beispiel #1
0
    def _transform(self, src_img, src_bbox, dst_size, dst_bbox, image_opts):
        """
        Do a 'real' transformation with a transformed mesh (see above).
        """
        src_bbox = self.src_srs.align_bbox(src_bbox)
        dst_bbox = self.dst_srs.align_bbox(dst_bbox)
        src_size = src_img.size
        src_quad = (0, 0, src_size[0], src_size[1])
        dst_quad = (0, 0, dst_size[0], dst_size[1])
        to_src_px = make_lin_transf(src_bbox, src_quad)
        to_dst_w = make_lin_transf(dst_quad, dst_bbox)
        meshes = []

        def dst_quad_to_src(quad):
            src_quad = []
            for dst_px in [(quad[0], quad[1]), (quad[0], quad[3]), (quad[2], quad[3]), (quad[2], quad[1])]:
                dst_w = to_dst_w((dst_px[0] + 0.5, dst_px[1] + 0.5))
                src_w = self.dst_srs.transform_to(self.src_srs, dst_w)
                src_px = to_src_px(src_w)
                src_quad.extend(src_px)
            return quad, src_quad

        mesh_div = self.mesh_div
        while mesh_div > 1 and (dst_size[0] / mesh_div < 10 or dst_size[1] / mesh_div < 10):
            mesh_div -= 1
        for quad in griddify(dst_quad, mesh_div):
            meshes.append(dst_quad_to_src(quad))

        result = src_img.as_image().transform(dst_size, Image.MESH, meshes, image_filter[image_opts.resampling])
        return ImageSource(result, size=dst_size, image_opts=image_opts)
Beispiel #2
0
    def _transform(self, src_img, src_bbox, dst_size, dst_bbox, image_opts):
        """
        Do a 'real' transformation with a transformed mesh (see above).
        """
        src_bbox = self.src_srs.align_bbox(src_bbox)
        dst_bbox = self.dst_srs.align_bbox(dst_bbox)
        src_size = src_img.size
        src_quad = (0, 0, src_size[0], src_size[1])
        dst_quad = (0, 0, dst_size[0], dst_size[1])
        to_src_px = make_lin_transf(src_bbox, src_quad)
        to_dst_w = make_lin_transf(dst_quad, dst_bbox)
        meshes = []

        def dst_quad_to_src(quad):
            src_quad = []
            for dst_px in [(quad[0], quad[1]), (quad[0], quad[3]),
                           (quad[2], quad[3]), (quad[2], quad[1])]:
                dst_w = to_dst_w((dst_px[0] + 0.5, dst_px[1] + 0.5))
                src_w = self.dst_srs.transform_to(self.src_srs, dst_w)
                src_px = to_src_px(src_w)
                src_quad.extend(src_px)
            return quad, src_quad

        mesh_div = self.mesh_div
        while mesh_div > 1 and (dst_size[0] / mesh_div < 10
                                or dst_size[1] / mesh_div < 10):
            mesh_div -= 1
        for quad in griddify(dst_quad, mesh_div):
            meshes.append(dst_quad_to_src(quad))

        result = src_img.as_image().transform(
            dst_size, Image.MESH, meshes, image_filter[image_opts.resampling])
        return ImageSource(result, size=dst_size, image_opts=image_opts)
Beispiel #3
0
    def _get_transformed_query(self, query):
        """
        Handle FI requests for unsupported SRS.
        """
        req_srs = query.srs
        req_bbox = query.bbox
        req_coord = make_lin_transf((0, 0, query.size[0], query.size[1]), req_bbox)(query.pos)

        info_srs = self._best_supported_srs(req_srs)
        info_bbox = req_srs.transform_bbox_to(info_srs, req_bbox)
        # calculate new info_size to keep square pixels after transform_bbox_to
        info_aratio = (info_bbox[3] - info_bbox[1])/(info_bbox[2] - info_bbox[0])
        info_size = query.size[0], int(info_aratio*query.size[0])

        info_coord = req_srs.transform_to(info_srs, req_coord)
        info_pos = make_lin_transf((info_bbox), (0, 0, info_size[0], info_size[1]))(info_coord)
        info_pos = int(round(info_pos[0])), int(round(info_pos[1]))

        info_query = InfoQuery(
            bbox=info_bbox,
            size=info_size,
            srs=info_srs,
            pos=info_pos,
            info_format=query.info_format,
            feature_count=query.feature_count,
        )
        return info_query
Beispiel #4
0
    def _get_transformed_query(self, query):
        """
        Handle FI requests for unsupported SRS.
        """
        req_srs = query.srs
        req_bbox = query.bbox
        req_coord = make_lin_transf((0, 0, query.size[0], query.size[1]),
                                    req_bbox)(query.pos)

        info_srs = self.supported_srs.best_srs(req_srs)
        info_bbox = req_srs.transform_bbox_to(info_srs, req_bbox)
        # calculate new info_size to keep square pixels after transform_bbox_to
        info_aratio = (info_bbox[3] - info_bbox[1]) / (info_bbox[2] -
                                                       info_bbox[0])
        info_size = query.size[0], int(info_aratio * query.size[0])

        info_coord = req_srs.transform_to(info_srs, req_coord)
        info_pos = make_lin_transf(
            (info_bbox), (0, 0, info_size[0], info_size[1]))(info_coord)
        info_pos = int(round(info_pos[0])), int(round(info_pos[1]))

        info_query = InfoQuery(
            bbox=info_bbox,
            size=info_size,
            srs=info_srs,
            pos=info_pos,
            info_format=query.info_format,
            feature_count=query.feature_count,
        )
        return info_query
Beispiel #5
0
def image_mask_from_geom(size, bbox, polygons):
    mask = Image.new('L', size, 255)
    if len(polygons) == 0:
        return mask

    transf = make_lin_transf(bbox, (0, 0) + size)

    # use negative ~.1 pixel buffer
    buffer = -0.1 * min((bbox[2] - bbox[0]) / size[0], (bbox[3] - bbox[1]) / size[1])

    draw = ImageDraw.Draw(mask)

    def draw_polygon(p):
        draw.polygon([transf(coord) for coord in p.exterior.coords], fill=0)
        for ring in p.interiors:
            draw.polygon([transf(coord) for coord in ring.coords], fill=255)

    for p in polygons:
        # little bit smaller polygon does not include touched pixels outside coverage
        buffered = p.buffer(buffer, resolution=1, join_style=2)

        if buffered.is_empty: # can be empty after negative buffer
            continue

        if buffered.type == 'MultiPolygon':
            # negative buffer can turn polygon into multipolygon
            for p in buffered:
                draw_polygon(p)
        else:
            draw_polygon(buffered)

    return mask
Beispiel #6
0
    def _transform_simple(self, src_img, src_bbox, dst_size, dst_bbox, image_opts):
        """
        Do a simple crop/extent transformation.
        """
        src_quad = (0, 0, src_img.size[0], src_img.size[1])
        to_src_px = make_lin_transf(src_bbox, src_quad)
        minx, miny = to_src_px((dst_bbox[0], dst_bbox[3]))
        maxx, maxy = to_src_px((dst_bbox[2], dst_bbox[1]))

        src_res = ((src_bbox[0]-src_bbox[2])/src_img.size[0],
                   (src_bbox[1]-src_bbox[3])/src_img.size[1])
        dst_res = ((dst_bbox[0]-dst_bbox[2])/dst_size[0],
                   (dst_bbox[1]-dst_bbox[3])/dst_size[1])

        tenth_px_res = (abs(dst_res[0]/(dst_size[0]*10)),
                        abs(dst_res[1]/(dst_size[1]*10)))
        if (abs(src_res[0]-dst_res[0]) < tenth_px_res[0] and
            abs(src_res[1]-dst_res[1]) < tenth_px_res[1]):
            # rounding might result in subpixel inaccuracy
            # this exact resolutioni match should only happen in clients with
            # fixed resolutions like OpenLayers
            minx = int(round(minx))
            miny = int(round(miny))
            result = src_img.as_image().crop((minx, miny,
                                              minx+dst_size[0], miny+dst_size[1]))
        else:
            img = img_for_resampling(src_img.as_image(), image_opts.resampling)
            result = img.transform(dst_size, Image.EXTENT,
                                                  (minx, miny, maxx, maxy),
                                                  image_filter[image_opts.resampling])
        return ImageSource(result, size=dst_size, image_opts=image_opts)
Beispiel #7
0
def image_mask_from_geom(size, bbox, polygons):
    mask = Image.new('L', size, 255)
    if len(polygons) == 0:
        return mask

    transf = make_lin_transf(bbox, (0, 0) + size)

    # use negative ~.1 pixel buffer
    buffer = -0.1 * min((bbox[2] - bbox[0]) / size[0],
                        (bbox[3] - bbox[1]) / size[1])

    draw = ImageDraw.Draw(mask)

    def draw_polygon(p):
        draw.polygon([transf(coord) for coord in p.exterior.coords], fill=0)
        for ring in p.interiors:
            draw.polygon([transf(coord) for coord in ring.coords], fill=255)

    for p in polygons:
        # little bit smaller polygon does not include touched pixels outside coverage
        buffered = p.buffer(buffer, resolution=1, join_style=2)

        if buffered.is_empty:  # can be empty after negative buffer
            continue

        if buffered.type == 'MultiPolygon':
            # negative buffer can turn polygon into multipolygon
            for p in buffered:
                draw_polygon(p)
        else:
            draw_polygon(buffered)

    return mask
Beispiel #8
0
    def _get_transformed_query(self, query):
        """
        Handle FI requests for unsupported SRS.
        """
        req_srs = query.srs
        req_bbox = query.bbox
        info_srs = self._best_supported_srs(req_srs)
        info_bbox = req_srs.transform_bbox_to(info_srs, req_bbox)

        req_coord = make_lin_transf((0, query.size[1], query.size[0], 0), req_bbox)(query.pos)

        info_coord = req_srs.transform_to(info_srs, req_coord)
        info_pos = make_lin_transf((info_bbox), (0, query.size[1], query.size[0], 0))(info_coord)

        info_query = InfoQuery(info_bbox, query.size, info_srs, info_pos, query.info_format)
        return info_query
Beispiel #9
0
    def _transform_simple(self, src_img, src_bbox, dst_size, dst_bbox, image_opts):
        """
        Do a simple crop/extent transformation.
        """
        src_quad = (0, 0, src_img.size[0], src_img.size[1])
        to_src_px = make_lin_transf(src_bbox, src_quad)
        minx, miny = to_src_px((dst_bbox[0], dst_bbox[3]))
        maxx, maxy = to_src_px((dst_bbox[2], dst_bbox[1]))

        src_res = ((src_bbox[0] - src_bbox[2]) / src_img.size[0], (src_bbox[1] - src_bbox[3]) / src_img.size[1])
        dst_res = ((dst_bbox[0] - dst_bbox[2]) / dst_size[0], (dst_bbox[1] - dst_bbox[3]) / dst_size[1])

        tenth_px_res = (abs(dst_res[0] / (dst_size[0] * 10)), abs(dst_res[1] / (dst_size[1] * 10)))
        if abs(src_res[0] - dst_res[0]) < tenth_px_res[0] and abs(src_res[1] - dst_res[1]) < tenth_px_res[1]:
            # rounding might result in subpixel inaccuracy
            # this exact resolutioni match should only happen in clients with
            # fixed resolutions like OpenLayers
            minx = int(round(minx))
            miny = int(round(miny))
            result = src_img.as_image().crop((minx, miny, minx + dst_size[0], miny + dst_size[1]))
        else:
            result = src_img.as_image().transform(
                dst_size, Image.EXTENT, (minx, miny, maxx, maxy), image_filter[image_opts.resampling]
            )
        return ImageSource(result, size=dst_size, image_opts=image_opts)
Beispiel #10
0
    def _get_transformed_query(self, query):
        """
        Handle FI requests for unsupported SRS.
        """
        req_srs = query.srs
        req_bbox = query.bbox
        info_srs = self._best_supported_srs(req_srs)
        info_bbox = req_srs.transform_bbox_to(info_srs, req_bbox)

        req_coord = make_lin_transf((0, query.size[1], query.size[0], 0),
                                    req_bbox)(query.pos)

        info_coord = req_srs.transform_to(info_srs, req_coord)
        info_pos = make_lin_transf(
            (info_bbox), (0, query.size[1], query.size[0], 0))(info_coord)

        info_query = InfoQuery(info_bbox, query.size, info_srs, info_pos,
                               query.info_format)
        return info_query
Beispiel #11
0
    def _transform(self, src_img, src_bbox, dst_size, dst_bbox, image_opts):
        """
        Do a 'real' transformation with a transformed mesh (see above).
        """
        src_bbox = self.src_srs.align_bbox(src_bbox)
        dst_bbox = self.dst_srs.align_bbox(dst_bbox)
        src_size = src_img.size
        src_quad = (0, 0, src_size[0], src_size[1])
        dst_quad = (0, 0, dst_size[0], dst_size[1])
        to_src_px = make_lin_transf(src_bbox, src_quad)
        to_dst_w = make_lin_transf(dst_quad, dst_bbox)
        meshes = []

        # more recent versions of Pillow use center coordinates for
        # transformations, we manually need to add half a pixel otherwise
        if transform_uses_center():
            px_offset = 0.0
        else:
            px_offset = 0.5

        def dst_quad_to_src(quad):
            src_quad = []
            for dst_px in [(quad[0], quad[1]), (quad[0], quad[3]),
                           (quad[2], quad[3]), (quad[2], quad[1])]:
                dst_w = to_dst_w(
                    (dst_px[0] + px_offset, dst_px[1] + px_offset))
                src_w = self.dst_srs.transform_to(self.src_srs, dst_w)
                src_px = to_src_px(src_w)
                src_quad.extend(src_px)
            return quad, src_quad

        mesh_div = self.mesh_div
        while mesh_div > 1 and (dst_size[0] / mesh_div < 10
                                or dst_size[1] / mesh_div < 10):
            mesh_div -= 1
        for quad in griddify(dst_quad, mesh_div):
            meshes.append(dst_quad_to_src(quad))

        img = img_for_resampling(src_img.as_image(), image_opts.resampling)
        result = img.transform(dst_size, Image.MESH, meshes,
                               image_filter[image_opts.resampling])
        return ImageSource(result, size=dst_size, image_opts=image_opts)
Beispiel #12
0
def image_mask_from_geom(img, bbox, polygons):
    transf = make_lin_transf(bbox, (0, 0) + img.size)

    mask = Image.new("L", img.size, 255)
    draw = ImageDraw.Draw(mask)

    for p in polygons:
        draw.polygon([transf(coord) for coord in p.exterior.coords], fill=0)
        for ring in p.interiors:
            draw.polygon([transf(coord) for coord in ring.coords], fill=255)

    return mask
Beispiel #13
0
def image_mask_from_geom(img, bbox, polygons):
    transf = make_lin_transf(bbox, (0, 0) + img.size)

    mask = Image.new('L', img.size, 255)
    draw = ImageDraw.Draw(mask)

    for p in polygons:
        draw.polygon([transf(coord) for coord in p.exterior.coords], fill=0)
        for ring in p.interiors:
            draw.polygon([transf(coord) for coord in ring.coords], fill=255)

    return mask
Beispiel #14
0
    def _transform(self, src_img, src_bbox, dst_size, dst_bbox, image_opts):
        """
        Do a 'real' transformation with a transformed mesh (see above).
        """
        src_bbox = self.src_srs.align_bbox(src_bbox)
        dst_bbox = self.dst_srs.align_bbox(dst_bbox)
        src_size = src_img.size
        src_quad = (0, 0, src_size[0], src_size[1])
        dst_quad = (0, 0, dst_size[0], dst_size[1])
        to_src_px = make_lin_transf(src_bbox, src_quad)
        to_dst_w = make_lin_transf(dst_quad, dst_bbox)
        meshes = []

        # more recent versions of Pillow use center coordinates for
        # transformations, we manually need to add half a pixel otherwise
        if transform_uses_center():
            px_offset = 0.0
        else:
            px_offset = 0.5

        def dst_quad_to_src(quad):
            src_quad = []
            for dst_px in [(quad[0], quad[1]), (quad[0], quad[3]),
                           (quad[2], quad[3]), (quad[2], quad[1])]:
                dst_w = to_dst_w((dst_px[0]+px_offset, dst_px[1]+px_offset))
                src_w = self.dst_srs.transform_to(self.src_srs, dst_w)
                src_px = to_src_px(src_w)
                src_quad.extend(src_px)
            return quad, src_quad

        mesh_div = self.mesh_div
        while mesh_div > 1 and (dst_size[0] / mesh_div < 10 or dst_size[1] / mesh_div < 10):
            mesh_div -= 1
        for quad in griddify(dst_quad, mesh_div):
            meshes.append(dst_quad_to_src(quad))

        img = img_for_resampling(src_img.as_image(), image_opts.resampling)
        result = img.transform(dst_size, Image.MESH, meshes,
                                              image_filter[image_opts.resampling])
        return ImageSource(result, size=dst_size, image_opts=image_opts)
Beispiel #15
0
    def _get_transformed_query(self, query):
        """
        Handle FI requests for unsupported SRS.
        """
        req_srs = query.srs
        req_bbox = query.bbox
        info_srs = self._best_supported_srs(req_srs)
        info_bbox = req_srs.transform_bbox_to(info_srs, req_bbox)

        req_coord = make_lin_transf((0, query.size[1], query.size[0], 0), req_bbox)(query.pos)

        info_coord = req_srs.transform_to(info_srs, req_coord)
        info_pos = make_lin_transf((info_bbox), (0, query.size[1], query.size[0], 0))(info_coord)
        info_pos = int(round(info_pos[0])), int(round(info_pos[1]))

        info_query = InfoQuery(
            bbox=info_bbox,
            size=query.size,
            srs=info_srs,
            pos=info_pos,
            info_format=query.info_format,
            feature_count=query.feature_count,
        )
        return info_query
Beispiel #16
0
def bbox_position_in_image(bbox, size, src_bbox):
    """
    Calculate the position of ``bbox`` in an image of ``size`` and ``src_bbox``.
    Returns the sub-image size and the offset in pixel from top-left corner
    and the sub-bbox.

    >>> bbox_position_in_image((-180, -90, 180, 90), (600, 300), (-180, -90, 180, 90))
    ((600, 300), (0, 0), (-180, -90, 180, 90))
    >>> bbox_position_in_image((-200, -100, 200, 100), (600, 300), (-180, -90, 180, 90))
    ((540, 270), (30, 15), (-180, -90, 180, 90))
    >>> bbox_position_in_image((-200, -50, 200, 100), (600, 300), (-180, -90, 180, 90))
    ((540, 280), (30, 20), (-180, -50, 180, 90))
    >>> bbox_position_in_image((586400,196400,752800,362800), (256, 256), (586400,196400,752800,350000))
    ((256, 237), (0, 19), (586400, 196400, 752800, 350000))
    """
    coord_to_px = make_lin_transf(bbox, (0, 0) + size)
    offsets = [0, size[1], size[0], 0]
    sub_bbox = list(bbox)
    if src_bbox[0] > bbox[0]:
        sub_bbox[0] = src_bbox[0]
        x, y = coord_to_px((src_bbox[0], 0))
        offsets[0] = int(x)
    if src_bbox[1] > bbox[1]:
        sub_bbox[1] = src_bbox[1]
        x, y = coord_to_px((0, src_bbox[1]))
        offsets[1] = int(y)

    if src_bbox[2] < bbox[2]:
        sub_bbox[2] = src_bbox[2]
        x, y = coord_to_px((src_bbox[2], 0))
        offsets[2] = int(x)

    if src_bbox[3] < bbox[3]:
        sub_bbox[3] = src_bbox[3]
        x, y = coord_to_px((0, src_bbox[3]))
        offsets[3] = int(y)

    size = abs(offsets[2] - offsets[0]), abs(offsets[1] - offsets[3])
    return size, (offsets[0], offsets[3]), tuple(sub_bbox)
Beispiel #17
0
def bbox_position_in_image(bbox, size, src_bbox):
    """
    Calculate the position of ``bbox`` in an image of ``size`` and ``src_bbox``.
    Returns the sub-image size and the offset in pixel from top-left corner
    and the sub-bbox.

    >>> bbox_position_in_image((-180, -90, 180, 90), (600, 300), (-180, -90, 180, 90))
    ((600, 300), (0, 0), (-180, -90, 180, 90))
    >>> bbox_position_in_image((-200, -100, 200, 100), (600, 300), (-180, -90, 180, 90))
    ((540, 270), (30, 15), (-180, -90, 180, 90))
    >>> bbox_position_in_image((-200, -50, 200, 100), (600, 300), (-180, -90, 180, 90))
    ((540, 280), (30, 20), (-180, -50, 180, 90))
    >>> bbox_position_in_image((586400,196400,752800,362800), (256, 256), (586400,196400,752800,350000))
    ((256, 237), (0, 19), (586400, 196400, 752800, 350000))
    """
    coord_to_px = make_lin_transf(bbox, (0, 0) + size)
    offsets = [0, size[1], size[0], 0]
    sub_bbox = list(bbox)
    if src_bbox[0] > bbox[0]:
        sub_bbox[0] = src_bbox[0]
        x, y = coord_to_px((src_bbox[0], 0))
        offsets[0] = int(x)
    if src_bbox[1] > bbox[1]:
        sub_bbox[1] = src_bbox[1]
        x, y = coord_to_px((0, src_bbox[1]))
        offsets[1] = int(y)

    if src_bbox[2] < bbox[2]:
        sub_bbox[2] = src_bbox[2]
        x, y = coord_to_px((src_bbox[2], 0))
        offsets[2] = int(x)

    if src_bbox[3] < bbox[3]:
        sub_bbox[3] = src_bbox[3]
        x, y = coord_to_px((0, src_bbox[3]))
        offsets[3] = int(y)

    size = abs(offsets[2] - offsets[0]), abs(offsets[1] - offsets[3])
    return size, (offsets[0], offsets[3]), tuple(sub_bbox)
Beispiel #18
0
def bbox_position_in_image(bbox, size, src_bbox):
    """
    Calculate the position of ``bbox`` in an image of ``size`` and ``src_bbox``.
    Returns the sub-image size and the offset in pixel from top-left corner
    and the sub-bbox.

    >>> bbox_position_in_image((-180, -90, 180, 90), (600, 300), (-180, -90, 180, 90))
    ((600, 300), (0, 0), (-180, -90, 180, 90))
    >>> bbox_position_in_image((-200, -100, 200, 100), (600, 300), (-180, -90, 180, 90))
    ((540, 270), (30, 15), (-180, -90, 180, 90))
    >>> bbox_position_in_image((-200, -50, 200, 100), (600, 300), (-180, -90, 180, 90))
    ((540, 280), (30, 20), (-180, -50, 180, 90))
    """
    coord_to_px = make_lin_transf(bbox, (0, 0) + size)
    offsets = [0.0, float(size[1]), float(size[0]), 0.0]
    sub_bbox = list(bbox)
    if src_bbox[0] > bbox[0]:
        sub_bbox[0] = src_bbox[0]
        x, y = coord_to_px((src_bbox[0], 0))
        offsets[0] = x
    if src_bbox[1] > bbox[1]:
        sub_bbox[1] = src_bbox[1]
        x, y = coord_to_px((0, src_bbox[1]))
        offsets[1] = y

    if src_bbox[2] < bbox[2]:
        sub_bbox[2] = src_bbox[2]
        x, y = coord_to_px((src_bbox[2], 0))
        offsets[2] = x
    if src_bbox[3] < bbox[3]:
        sub_bbox[3] = src_bbox[3]
        x, y = coord_to_px((0, src_bbox[3]))
        offsets[3] = y

    size = int(offsets[2] - offsets[0]), int(offsets[1] - offsets[3])
    return size, (int(offsets[0]), int(offsets[3])), tuple(sub_bbox)
Beispiel #19
0
def bbox_position_in_image(bbox, size, src_bbox):
    """
    Calculate the position of ``bbox`` in an image of ``size`` and ``src_bbox``.
    Returns the sub-image size and the offset in pixel from top-left corner
    and the sub-bbox.

    >>> bbox_position_in_image((-180, -90, 180, 90), (600, 300), (-180, -90, 180, 90))
    ((600, 300), (0, 0), (-180, -90, 180, 90))
    >>> bbox_position_in_image((-200, -100, 200, 100), (600, 300), (-180, -90, 180, 90))
    ((540, 270), (30, 15), (-180, -90, 180, 90))
    >>> bbox_position_in_image((-200, -50, 200, 100), (600, 300), (-180, -90, 180, 90))
    ((540, 280), (30, 20), (-180, -50, 180, 90))
    """
    coord_to_px = make_lin_transf(bbox, (0, 0) + size)
    offsets = [0.0, float(size[1]), float(size[0]), 0.0]
    sub_bbox = list(bbox)
    if src_bbox[0] > bbox[0]:
        sub_bbox[0] = src_bbox[0]
        x, y = coord_to_px((src_bbox[0], 0))
        offsets[0] = x
    if src_bbox[1] > bbox[1]:
        sub_bbox[1] = src_bbox[1]
        x, y = coord_to_px((0, src_bbox[1]))
        offsets[1] = y

    if src_bbox[2] < bbox[2]:
        sub_bbox[2] = src_bbox[2]
        x, y = coord_to_px((src_bbox[2], 0))
        offsets[2] = x
    if src_bbox[3] < bbox[3]:
        sub_bbox[3] = src_bbox[3]
        x, y = coord_to_px((0, src_bbox[3]))
        offsets[3] = y

    size = int(offsets[2] - offsets[0]), int(offsets[1] - offsets[3])
    return size, (int(offsets[0]), int(offsets[3])), tuple(sub_bbox)
Beispiel #20
0
 def _get_pos(self):
     size = self.size
     vals = self['geometry'].split(',')
     x, y = float(vals[0]), float(vals[1])
     return make_lin_transf(self.bbox, (0, 0, size[0], size[1]))((x, y))
Beispiel #21
0
 def pos_coords(self):
     """x, y query coordinates (in request SRS)"""
     width, height = self.size
     bbox = self.bbox
     return make_lin_transf((0, 0, width, height), bbox)(self.pos)
Beispiel #22
0
 def pos_coords(self):
     """x, y query coordinates (in request SRS)"""
     width, height = self.size
     bbox = self.bbox
     return make_lin_transf((0, 0, width, height), bbox)(self.pos)
Beispiel #23
0
 def _set_pos(self, value):
     size = self.size
     req_coord = make_lin_transf((0, 0, size[0], size[1]), self.bbox)(value)
     self['geometry'] = '%f,%f' % req_coord
Beispiel #24
0
 def _get_pos(self):
     size = self.size
     vals = self["geometry"].split(",")
     x, y = float(vals[0]), float(vals[1])
     return make_lin_transf(self.bbox, (0, 0, size[0], size[1]))((x, y))
Beispiel #25
0
 def _set_pos(self, value):
     size = self.size
     req_coord = make_lin_transf((0, 0, size[0], size[1]), self.bbox)(value)
     self["geometry"] = "%f,%f" % req_coord
Beispiel #26
0
 def coord(self):
     return make_lin_transf((0, self.size[1], self.size[0], 0), self.bbox)(self.pos)
Beispiel #27
0
 def coord(self):
     return make_lin_transf((0, 0, self.size[0], self.size[1]),
                            self.bbox)(self.pos)
Beispiel #28
0
def transform_meshes(src_size, src_bbox, src_srs, dst_size, dst_bbox, dst_srs, max_px_err=1):
    """
    transform_meshes creates a list of QUAD transformation parameters for PIL's
    MESH image transformation.

    Each QUAD is a rectangle in the destination image, like ``(0, 0, 100, 100)`` and
    a list of four pixel coordinates in the source image that match the destination rectangle.
    The four points form a quadliteral (i.e. not a rectangle).
    PIL's image transform uses affine transformation to fill each rectangle in the destination
    image with data from the source quadliteral.

    The number of QUADs is calculated dynamically to keep the deviation in the image
    transformation below one pixel. Image transformations for large map scales can be transformed with
    1-4 QUADs most of the time. For low scales, transform_meshes can generate a few hundred QUADs.

    It generates a maximum of one QUAD per 50 pixel.
    """
    src_bbox = src_srs.align_bbox(src_bbox)
    dst_bbox = dst_srs.align_bbox(dst_bbox)
    src_rect = (0, 0, src_size[0], src_size[1])
    dst_rect = (0, 0, dst_size[0], dst_size[1])
    to_src_px = make_lin_transf(src_bbox, src_rect)
    to_src_w = make_lin_transf(src_rect, src_bbox)
    to_dst_w = make_lin_transf(dst_rect, dst_bbox)
    meshes = []

    # more recent versions of Pillow use center coordinates for
    # transformations, we manually need to add half a pixel otherwise
    if transform_uses_center():
        px_offset = 0.0
    else:
        px_offset = 0.5

    def dst_quad_to_src(quad):
        src_quad = []
        for dst_px in [(quad[0], quad[1]), (quad[0], quad[3]),
                        (quad[2], quad[3]), (quad[2], quad[1])]:
            dst_w = to_dst_w(
                (dst_px[0] + px_offset, dst_px[1] + px_offset))
            src_w = dst_srs.transform_to(src_srs, dst_w)
            src_px = to_src_px(src_w)
            src_quad.extend(src_px)

        return quad, src_quad

    res = (dst_bbox[2] - dst_bbox[0]) / dst_size[0]
    max_err = max_px_err * res

    def is_good(quad, src_quad):
        w = quad[2] - quad[0]
        h = quad[3] - quad[1]

        if w < 50 or h < 50:
            return True

        xc = quad[0] + w / 2.0 - 0.5
        yc = quad[1] + h / 2.0 - 0.5

        # coordinate for the center of the quad
        dst_w = to_dst_w((xc, yc))

        # actual coordinate for the center of the quad
        src_px = center_quad_transform(quad, src_quad)
        real_dst_w = src_srs.transform_to(dst_srs, to_src_w(src_px))

        err = max(abs(dst_w[0] - real_dst_w[0]), abs(dst_w[1] - real_dst_w[1]))
        return err < max_err


    # recursively add meshes. divide each quad into four sub quad till
    # accuracy is good enough.
    def add_meshes(quads):
        for quad in quads:
            quad, src_quad = dst_quad_to_src(quad)
            if is_good(quad, src_quad):
                meshes.append((quad, src_quad))
            else:
                add_meshes(divide_quad(quad))

    add_meshes([(0, 0, dst_size[0], dst_size[1])])
    return meshes