def twms_main(data): """ Do main TWMS work. data - dictionary of params. returns (error_code, content_type, resp) """ start_time = datetime.datetime.now() content_type = "text/html" resp = "" srs = data.get("srs", "EPSG:4326") gpx = data.get("gpx", "").split(",") if gpx == ['']: gpx = [] wkt = data.get("wkt", "") trackblend = float(data.get("trackblend", "0.5")) color = data.get("color", data.get("colour", "")).split(",") track = False tracks = [] if len(gpx) == 0: req_bbox = projections.from4326( (27.6518898, 53.8683186, 27.6581944, 53.8720359), srs) else: for g in gpx: local_gpx = config.gpx_cache + "%s.gpx" % g if not os.path.exists(config.gpx_cache): os.makedirs(config.gpx_cache) if not os.path.exists(local_gpx): urllib.urlretrieve( "http://www.openstreetmap.org/trace/%s/data" % g, local_gpx) if not track: track = GPXParser(local_gpx) req_bbox = projections.from4326(track.bbox, srs) else: track = GPXParser(local_gpx) req_bbox = bbox.add(req_bbox, projections.from4326(track.bbox, srs)) tracks.append(track) req_type = data.get("request", "GetMap") version = data.get("version", "1.1.1") ref = data.get("ref", config.service_url) if req_type == "GetCapabilities": content_type, resp = capabilities.get(version, ref) return (OK, content_type, resp) layer = data.get("layers", config.default_layers).split(",") if ("layers" in data) and not layer[0]: layer = ["transparent"] if req_type == "GetCorrections": points = data.get("points", data.get("POINTS", "")).split("=") resp = "" points = [a.split(",") for a in points] points = [(float(a[0]), float(a[1])) for a in points] req.content_type = "text/plain" for lay in layer: for point in points: resp += "%s,%s;" % tuple( correctify.rectify(config.layers[lay], point)) resp += "\n" return (OK, content_type, resp) force = data.get("force", "") if force != "": force = force.split(",") force = tuple(force) filt = data.get("filt", "") if filt != "": filt = filt.split(",") filt = tuple(filt) if layer == [""]: content_type = "text/html" resp = overview.html(ref) return (OK, content_type, resp) format = data.get("format", config.default_format).lower() format = formats.get("image/" + format, format) format = formats.get(format, format) if format not in formats.values(): return (ERROR, content_type, "Invalid format") content_type = mimetypes[format] width = 0 height = 0 resp_cache_path, resp_ext = "", "" if req_type == "GetTile": width = 256 height = 256 height = int(data.get("height", height)) width = int(data.get("width", width)) srs = data.get("srs", "EPSG:3857") x = int(data.get("x", 0)) y = int(data.get("y", 0)) z = int(data.get("z", 1)) + 1 if "cache_tile_responses" in dir(config) and not wkt and (len(gpx) == 0): if (srs, tuple(layer), filt, width, height, force, format) in config.cache_tile_responses: resp_cache_path, resp_ext = config.cache_tile_responses[( srs, tuple(layer), filt, width, height, force, format)] resp_cache_path = resp_cache_path + "/%s/%s/%s.%s" % ( z - 1, x, y, resp_ext) if os.path.exists(resp_cache_path): return (OK, content_type, open(resp_cache_path, "r").read()) if len(layer) == 1: if layer[0] in config.layers: if config.layers[layer[0]][ "proj"] == srs and width is 256 and height is 256 and not filt and not force and not correctify.has_corrections( config.layers[layer[0]]): local = config.tiles_cache + config.layers[ layer[0]]["prefix"] + "/z%s/%s/x%s/%s/y%s." % ( z, x / 1024, x, y / 1024, y) ext = config.layers[layer]["ext"] adds = ["", "ups."] for add in adds: if os.path.exists(local + add + ext): tile_file = open(local + add + ext, "r") resp = tile_file.read() return (OK, content_type, resp) req_bbox = projections.from4326(projections.bbox_by_tile(z, x, y, srs), srs) if data.get("bbox", None): req_bbox = tuple(map(float, data.get("bbox", req_bbox).split(","))) req_bbox = projections.to4326(req_bbox, srs) req_bbox, flip_h = bbox.normalize(req_bbox) box = req_bbox #print(req_bbox, file=sys.stderr) #sys.stderr.flush() height = int(data.get("height", height)) width = int(data.get("width", width)) width = min(width, config.max_width) height = min(height, config.max_height) if (width == 0) and (height == 0): width = 350 # layer = layer.split(",") imgs = 1. ll = layer.pop(0) if ll[-2:] == "!c": ll = ll[:-2] if wkt: wkt = "," + wkt wkt = correctify.corr_wkt(config.layers[ll]) + wkt srs = config.layers[ll]["proj"] try: result_img = getimg(box, srs, (height, width), config.layers[ll], start_time, force) except KeyError: result_img = Image.new("RGBA", (width, height)) #width, height = result_img.size for ll in layer: if ll[-2:] == "!c": ll = ll[:-2] if wkt: wkt = "," + wkt wkt = correctify.corr_wkt(config.layers[ll]) + wkt srs = config.layers[ll]["proj"] im2 = getimg(box, srs, (height, width), config.layers[ll], start_time, force) if "empty_color" in config.layers[ll]: ec = ImageColor.getcolor(config.layers[ll]["empty_color"], "RGBA") sec = set(ec) if "empty_color_delta" in config.layers[ll]: delta = config.layers[ll]["empty_color_delta"] for tr in range(-delta, delta): for tg in range(-delta, delta): for tb in range(-delta, delta): if (ec[0] + tr) >= 0 and (ec[0] + tr) < 256 and ( ec[1] + tr ) >= 0 and (ec[1] + tr) < 256 and ( ec[2] + tr) >= 0 and (ec[2] + tr) < 256: sec.add((ec[0] + tr, ec[1] + tg, ec[2] + tb, ec[3])) i2l = im2.load() for x in range(0, im2.size[0]): for y in range(0, im2.size[1]): t = i2l[x, y] if t in sec: i2l[x, y] = (t[0], t[1], t[2], 0) if not im2.size == result_img.size: im2 = im2.resize(result_img.size, Image.ANTIALIAS) im2 = Image.composite(im2, result_img, im2.split()[3]) # imgs/(imgs+1.)) if "noblend" in force: result_img = im2 else: result_img = Image.blend(im2, result_img, 0.5) imgs += 1. ##Applying filters result_img = filter.raster(result_img, filt, req_bbox, srs) #print(wkt, file=sys.stderr) #sys.stderr.flush() if wkt: result_img = drawing.wkt(wkt, result_img, req_bbox, srs, color if len(color) > 0 else None, trackblend) if len(gpx) > 0: last_color = None c = iter(color) for track in tracks: try: last_color = c.next() except StopIteration: pass result_img = drawing.gpx(track, result_img, req_bbox, srs, last_color, trackblend) if flip_h: result_img = ImageOps.flip(result_img) image_content = BytesIO() if format == "JPEG": try: result_img.save(image_content, format, quality=config.output_quality, progressive=config.output_progressive) except IOError: result_img.save(image_content, format, quality=config.output_quality) elif format == "PNG": result_img.save(image_content, format, progressive=config.output_progressive, optimize=config.output_optimize) elif format == "GIF": result_img.save(image_content, format, quality=config.output_quality, progressive=config.output_progressive) else: ## workaround for GIF result_img = result_img.convert("RGB") result_img.save(image_content, format, quality=config.output_quality, progressive=config.output_progressive) resp = image_content.getvalue() if resp_cache_path: try: "trying to create local cache directory, if it doesn't exist" os.makedirs("/".join(resp_cache_path.split("/")[:-1])) except OSError: pass try: a = open(resp_cache_path, "w") a.write(resp) a.close() except (OSError, IOError): print("error saving response answer to file %s." % (resp_cache_path), file=sys.stderr) sys.stderr.flush() return (OK, content_type, resp)
def twms_main(data): """ Do main TWMS work. data - dictionary of params. returns (error_code, content_type, resp) """ start_time = datetime.datetime.now() content_type = "text/html" resp = "" srs = data.get("srs", "EPSG:4326") gpx = data.get("gpx","").split(",") wkt = data.get("wkt","") trackblend = float(data.get("trackblend","0.5")) color = data.get("color",data.get("colour","")).split(",") track = False tracks = [] if len(gpx) == 0: req_bbox = projections.from4326((27.6518898,53.8683186,27.6581944,53.8720359), srs) else: for g in gpx: local_gpx = config.gpx_cache + "%s.gpx" % g if not os.path.exists (config.gpx_cache): os.makedirs(config.gpx_cache) if not os.path.exists (local_gpx): urllib.urlretrieve ("http://www.openstreetmap.org/trace/%s/data" % g, local_gpx) if not track: track = GPXParser(local_gpx) req_bbox = projections.from4326(track.bbox, srs) else: track = GPXParser(local_gpx) req_bbox = bbox.add(req_bbox, projections.from4326(track.bbox, srs)) tracks.append(track) req_type = data.get("request","GetMap") version = data.get("version","1.1.1") ref = data.get("ref",config.service_url) if req_type == "GetCapabilities": content_type, resp = capabilities.get(version, ref) return (OK, content_type, resp) layer = data.get("layers",config.default_layers).split(",") if ("layers" in data) and not layer[0]: layer = ["transparent"] if req_type == "GetCorrections": points = data.get("points",data.get("POINTS", "")).split("=") resp = "" points = [a.split(",") for a in points] points = [(float(a[0]), float(a[1])) for a in points] req.content_type = "text/plain" for lay in layer: for point in points: resp += "%s,%s;"% tuple(correctify.rectify(config.layers[lay], point)) resp += "\n" return (OK, content_type, resp) force = tuple(data.get("force","").split(",")) filt = tuple(data.get("filter","").split(",")) if layer == [""] : content_type = "text/html" resp = overview.html(ref) return (OK, content_type, resp) format = data.get("format", config.default_format).lower() format = formats.get("image/" + format, format) format = formats.get(format, format) if format not in formats.values(): return (ERROR, content_type, "Invalid format") content_type = mimetypes[format] width=0 height=0 resp_cache_path, resp_ext = "","" if req_type == "GetTile": width=256 height=256 height = int(data.get("height",height)) width = int(data.get("width",width)) srs = data.get("srs", "EPSG:3857") x = int(data.get("x",0)) y = int(data.get("y",0)) z = int(data.get("z",1)) + 1 if "cache_tile_responses" in dir(config) and not wkt and (len(gpx) == 0): if (srs, tuple(layer), filt, width, height, force, format) in config.cache_tile_responses: resp_cache_path, resp_ext = config.cache_tile_responses[(srs, tuple(layer), filt, width, height, force, format)] resp_cache_path = resp_cache_path+"/%s/%s/%s.%s"%(z-1,x,y,resp_ext) if os.path.exists(resp_cache_path): return (OK, content_type, open(resp_cache_path, "r").read()) if len(layer) == 1: if layer[0] in config.layers: if config.layers[layer[0]]["proj"] == srs and width is 256 and height is 256 and not filt and not force and not correctify.has_corrections(layer[0]): local = config.tiles_cache + config.layers[layer[0]]["prefix"] + "/z%s/%s/x%s/%s/y%s."%(z, x/1024, x, y/1024,y) ext = config.layers[layer]["ext"] adds = ["","ups."] for add in adds: if os.path.exists(local+add+ext): tile_file = open(local+add+ext, "r") resp = tile_file.read() return (OK, content_type, resp) req_bbox = projections.from4326(projections.bbox_by_tile(z,x,y,srs),srs) if data.get("bbox",None): req_bbox = tuple(map(float,data.get("bbox",req_bbox).split(","))) req_bbox = projections.to4326(req_bbox, srs) req_bbox, flip_h = bbox.normalize(req_bbox) box = req_bbox #print >> sys.stderr, req_bbox #sys.stderr.flush() height = int(data.get("height",height)) width = int(data.get("width",width)) width = min(width, config.max_width) height = min(height, config.max_height) if (width == 0) and (height == 0): width = 350 # layer = layer.split(",") imgs = 1. ll = layer.pop(0) if ll[-2:] == "!c": ll = ll[:-2] if wkt: wkt = ","+wkt wkt = correctify.corr_wkt(config.layers[ll]) + wkt srs = config.layers[ll]["proj"] try: result_img = getimg(box,srs, (height, width), config.layers[ll], start_time, force) except KeyError: result_img = Image.new("RGBA", (width,height)) #width, height = result_img.size for ll in layer: if ll[-2:] == "!c": ll = ll[:-2] if wkt: wkt = ","+wkt wkt = correctify.corr_wkt(config.layers[ll]) + wkt srs = config.layers[ll]["proj"] im2 = getimg(box, srs,(height, width), config.layers[ll], start_time, force) if "empty_color" in config.layers[ll]: ec = ImageColor.getcolor(config.layers[ll]["empty_color"], "RGBA") sec = set(ec) if "empty_color_delta" in config.layers[ll]: delta = config.layers[ll]["empty_color_delta"] for tr in range(-delta, delta): for tg in range(-delta, delta): for tb in range(-delta, delta): if (ec[0]+tr) >= 0 and (ec[0]+tr) < 256 and (ec[1]+tr) >= 0 and (ec[1]+tr) < 256 and(ec[2]+tr) >= 0 and (ec[2]+tr) < 256: sec.add((ec[0]+tr,ec[1]+tg,ec[2]+tb,ec[3])) i2l = im2.load() for x in range(0,im2.size[0]): for y in range(0,im2.size[1]): t = i2l[x,y] if t in sec: i2l[x,y] = (t[0],t[1],t[2],0) if not im2.size == result_img.size: im2 = im2.resize(result_img.size, Image.ANTIALIAS) im2 = Image.composite(im2,result_img, im2.split()[3]) # imgs/(imgs+1.)) if "noblend" in force: result_img = im2 else: result_img = Image.blend(im2, result_img, 0.5) imgs += 1. ##Applying filters result_img = filter.raster(result_img, filt, req_bbox, srs) #print >> sys.stderr, wkt #sys.stderr.flush() if wkt: result_img = drawing.wkt(wkt, result_img, req_bbox, srs, color if len(color) > 0 else None, trackblend) if len(gpx) > 0: last_color = None c = iter(color) for track in tracks: try: last_color = c.next(); except StopIteration: pass result_img = drawing.gpx(track, result_img, req_bbox, srs, last_color, trackblend) if flip_h: result_img = ImageOps.flip(result_img) image_content = StringIO.StringIO() if format == "JPEG": try: result_img.save(image_content, format, quality=config.output_quality, progressive=config.output_progressive) except IOError: result_img.save(image_content, format, quality=config.output_quality) elif format == "PNG": result_img.save(image_content, format, progressive=config.output_progressive, optimize =config.output_optimize) elif format == "GIF": result_img.save(image_content, format, quality=config.output_quality, progressive=config.output_progressive) else: ## workaround for GIF result_img = result_img.convert("RGB") result_img.save(image_content, format, quality=config.output_quality, progressive=config.output_progressive) resp = image_content.getvalue() if resp_cache_path: try: "trying to create local cache directory, if it doesn't exist" os.makedirs("/".join(resp_cache_path.split("/")[:-1])) except OSError: pass try: a = open(resp_cache_path, "w") a.write(resp) a.close() except (OSError, IOError): print >> sys.stderr, "error saving response answer to file %s." % (resp_cache_path) sys.stderr.flush() return (OK, content_type, resp)
def getimg(bbox, request_proj, size, layer, start_time, force): orig_bbox = bbox ## Making 4-corner maximal bbox bbox_p = projections.from4326(bbox, request_proj) bbox_p = projections.to4326((bbox_p[2], bbox_p[1], bbox_p[0], bbox_p[3]), request_proj) bbox_4 = ((bbox_p[2], bbox_p[3]), (bbox[0], bbox[1]), (bbox_p[0], bbox_p[1]), (bbox[2], bbox[3])) if "nocorrect" not in force: bb4 = [] for point in bbox_4: bb4.append(correctify.rectify(layer, point)) bbox_4 = bb4 bbox = bbox_utils.expand_to_point(bbox, bbox_4) #print(bbox) #print(orig_bbox) global cached_objs H, W = size max_zoom = layer.get("max_zoom", config.default_max_zoom) min_zoom = layer.get("min_zoom", 1) zoom = bbox_utils.zoom_for_bbox(bbox, size, layer, min_zoom, max_zoom, (config.max_height, config.max_width)) lo1, la1, lo2, la2 = bbox from_tile_x, from_tile_y, to_tile_x, to_tile_y = projections.tile_by_bbox( bbox, zoom, layer["proj"]) cut_from_x = int(256 * (from_tile_x - int(from_tile_x))) cut_from_y = int(256 * (from_tile_y - int(from_tile_y))) cut_to_x = int(256 * (to_tile_x - int(to_tile_x))) cut_to_y = int(256 * (to_tile_y - int(to_tile_y))) from_tile_x, from_tile_y = int(from_tile_x), int(from_tile_y) to_tile_x, to_tile_y = int(to_tile_x), int(to_tile_y) bbox_im = (cut_from_x, cut_to_y, 256 * (to_tile_x - from_tile_x) + cut_to_x, 256 * (from_tile_y - to_tile_y) + cut_from_y) x = 256 * (to_tile_x - from_tile_x + 1) y = 256 * (from_tile_y - to_tile_y + 1) #print(x, y, file=sys.stderr) #sys.stderr.flush() out = Image.new("RGBA", (x, y)) for x in range(from_tile_x, to_tile_x + 1): for y in range(to_tile_y, from_tile_y + 1): got_image = False im1 = tile_image(layer, zoom, x, y, start_time, real=True) if im1: if "prefix" in layer: if (layer["prefix"], zoom, x, y) not in cached_objs: if im1.is_ok: cached_objs[(layer["prefix"], zoom, x, y)] = im1 cached_hist_list.append( (layer["prefix"], zoom, x, y)) #print((layer["prefix"], zoom, x, y), cached_objs[(layer["prefix"], zoom, x, y)], file=sys.stderr) #sys.stderr.flush() if len(cached_objs) >= config.max_ram_cached_tiles: del cached_objs[cached_hist_list.pop(0)] #print("Removed tile from cache", file=sys.stderr) #sys.stderr.flush() else: ec = ImageColor.getcolor( layer.get("empty_color", config.default_background), "RGBA") #ec = (ec[0],ec[1],ec[2],0) im1 = Image.new("RGBA", (256, 256), ec) out.paste(im1, ( (x - from_tile_x) * 256, (-to_tile_y + y) * 256, )) if "filter" in layer: out = filter.raster(out, layer["filter"], orig_bbox, request_proj) ## TODO: Here's a room for improvement. we could drop this crop in case user doesn't need it. out = out.crop(bbox_im) if "noresize" not in force: if (H == W) and (H == 0): W, H = out.size if H == 0: H = out.size[1] * W // out.size[0] if W == 0: W = out.size[0] * H // out.size[1] #bbox = orig_bbox quad = [] trans_needed = False for point in bbox_4: x = (point[0] - bbox[0]) / (bbox[2] - bbox[0]) * (out.size[0]) y = (1 - (point[1] - bbox[1]) / (bbox[3] - bbox[1])) * (out.size[1]) x = int(round(x)) y = int(round(y)) if (x is not 0 and x is not out.size[0]) or (y is not 0 and y is not out.size[1]): trans_needed = True quad.append(x) quad.append(y) if trans_needed: quad = tuple(quad) out = out.transform((W, H), Image.QUAD, quad, Image.BICUBIC) elif (W != out.size[0]) or (H != out.size[1]): "just resize" out = out.resize((W, H), Image.ANTIALIAS) # out = reproject(out, bbox, layer["proj"], request_proj) return out
def getimg (bbox, request_proj, size, layer, start_time, force): orig_bbox = bbox ## Making 4-corner maximal bbox bbox_p = projections.from4326(bbox, request_proj) bbox_p = projections.to4326((bbox_p[2],bbox_p[1],bbox_p[0],bbox_p[3]), request_proj) bbox_4 = ( (bbox_p[2],bbox_p[3]),(bbox[0], bbox[1]),(bbox_p[0],bbox_p[1]),(bbox[2],bbox[3]) ) if "nocorrect" not in force: bb4 = [] for point in bbox_4: bb4.append(correctify.rectify(layer, point)) bbox_4 = bb4 bbox = bbox_utils.expand_to_point(bbox, bbox_4) #print bbox #print orig_bbox global cached_objs H,W = size max_zoom = layer.get("max_zoom",config.default_max_zoom) min_zoom = layer.get("min_zoom",1) zoom = bbox_utils.zoom_for_bbox (bbox,size,layer, min_zoom, max_zoom, (config.max_height,config.max_width)) lo1, la1, lo2, la2 = bbox from_tile_x, from_tile_y, to_tile_x, to_tile_y = projections.tile_by_bbox(bbox, zoom, layer["proj"]) cut_from_x = int(256*(from_tile_x - int(from_tile_x))) cut_from_y = int(256*(from_tile_y - int(from_tile_y))) cut_to_x = int(256*(to_tile_x - int(to_tile_x))) cut_to_y = int(256*(to_tile_y - int(to_tile_y))) from_tile_x, from_tile_y = int(from_tile_x), int(from_tile_y) to_tile_x, to_tile_y = int(to_tile_x), int(to_tile_y) bbox_im = (cut_from_x, cut_to_y, 256*(to_tile_x-from_tile_x)+cut_to_x, 256*(from_tile_y-to_tile_y)+cut_from_y ) x = 256*(to_tile_x-from_tile_x+1) y = 256*(from_tile_y-to_tile_y+1) #print >> sys.stderr, x, y #sys.stderr.flush() out = Image.new("RGBA", (x, y)) for x in range (from_tile_x, to_tile_x+1): for y in range (to_tile_y, from_tile_y+1): got_image = False im1 = tile_image (layer,zoom,x,y, start_time, real = True) if im1: if "prefix" in layer: if (layer["prefix"], zoom, x, y) not in cached_objs: if im1.is_ok: cached_objs[(layer["prefix"], zoom, x, y)] = im1 cached_hist_list.append((layer["prefix"], zoom, x, y)) #print >> sys.stderr, (layer["prefix"], zoom, x, y), cached_objs[(layer["prefix"], zoom, x, y)] #sys.stderr.flush() if len(cached_objs) >= config.max_ram_cached_tiles: del cached_objs[cached_hist_list.pop(0)] #print >> sys.stderr, "Removed tile from cache", #sys.stderr.flush() else: ec = ImageColor.getcolor(layer.get("empty_color", config.default_background), "RGBA") #ec = (ec[0],ec[1],ec[2],0) im1 = Image.new("RGBA", (256, 256), ec) out.paste(im1,((x - from_tile_x)*256, (-to_tile_y + y )*256,)) if "filter" in layer: out = filter.raster(out, layer["filter"], orig_bbox, request_proj) ## TODO: Here's a room for improvement. we could drop this crop in case user doesn't need it. out = out.crop(bbox_im) if "noresize" not in force: if (H == W) and (H == 0): W, H = out.size if H == 0: H = out.size[1]*W/out.size[0] if W == 0: W = out.size[0]*H/out.size[1] #bbox = orig_bbox quad = [] trans_needed = False for point in bbox_4: x = (point[0]-bbox[0])/(bbox[2]-bbox[0])*(out.size[0]) y = (1-(point[1]-bbox[1])/(bbox[3]-bbox[1]))*(out.size[1]) x = int(round(x)) y = int(round(y)) if (x is not 0 and x is not out.size[0]) or (y is not 0 and y is not out.size[1]): trans_needed = True quad.append(x) quad.append(y) if trans_needed: quad = tuple(quad) out = out.transform((W,H), Image.QUAD, quad, Image.BICUBIC) elif (W != out.size[0]) or (H != out.size[1]): "just resize" out = out.resize((W,H), Image.ANTIALIAS) # out = reproject(out, bbox, layer["proj"], request_proj) return out