def zoom_for_bbox (bbox, size, layer, min_zoom = 1, max_zoom = 18,max_size = (10000,10000)): """ Calculate a best-fit zoom level """ h,w = size for i in range (min_zoom,max_zoom): cx1, cy1, cx2, cy2 = projections.tile_by_bbox (bbox, i, layer["proj"]) if w is not 0: if (cx2-cx1)*256 >= w*0.9 : return i if h is not 0: if (cy1-cy2)*256 >= h*0.9: return i if (cy1-cy2)*256 >= max_size[0]/2: return i if (cx2-cx1)*256 >= max_size[1]/2: return i return max_zoom
def zoom_for_bbox (bbox, size, layer, min_zoom = 1, max_zoom = 18,max_size = (10000,10000)): """ Calculate a best-fit zoom level """ h,w = size for i in range (min_zoom,max_zoom): cx1, cy1, cx2, cy2 = projections.tile_by_bbox (bbox, i, layer["proj"]) if w is not 0: if (cx2-cx1)*256 >= w*0.9 : return i if h is not 0: if (cy1-cy2)*256 >= h*0.9: return i if (cy1-cy2)*256 >= max_size[0]/2: return i if (cx2-cx1)*256 >= max_size[1]/2: return i return max_zoom
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