Skip to content

Commit

Permalink
- improve render thumbnail procedure
Browse files Browse the repository at this point in the history
  • Loading branch information
afabiani committed Oct 12, 2018
1 parent 0b539b7 commit 0f7cd61
Show file tree
Hide file tree
Showing 9 changed files with 211 additions and 127 deletions.
2 changes: 0 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -84,5 +84,3 @@ geonode\.tests\.bdd\.e2e\.test_login/

/celerybeat.pid
/celerybeat-schedule

/celerybeat-schedule
Binary file removed celerybeat-schedule
Binary file not shown.
33 changes: 19 additions & 14 deletions geonode/base/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -985,6 +985,7 @@ def deg_len():
self.bbox_x1 = lon + distance_x_degrees
self.bbox_y0 = lat - distance_y_degrees
self.bbox_y1 = lat + distance_y_degrees
self.srid = 'EPSG:4326'

def set_bounds_from_bbox(self, bbox, srid):
"""
Expand All @@ -1009,24 +1010,28 @@ def set_bounds_from_bbox(self, bbox, srid):
self.bbox_y1 = bbox[3]
self.srid = srid

minx, maxx, miny, maxy = [float(c) for c in bbox]
x = (minx + maxx) / 2
y = (miny + maxy) / 2
(center_x, center_y) = forward_mercator((x, y))
if srid == "EPSG:4326":
minx, maxx, miny, maxy = [float(c) for c in bbox]
x = (minx + maxx) / 2
y = (miny + maxy) / 2
(center_x, center_y) = forward_mercator((x, y))

xdiff = maxx - minx
ydiff = maxy - miny
xdiff = maxx - minx
ydiff = maxy - miny

zoom = 0
zoom = 0

if xdiff > 0 and ydiff > 0:
width_zoom = math.log(360 / xdiff, 2)
height_zoom = math.log(360 / ydiff, 2)
zoom = math.ceil(min(width_zoom, height_zoom))
if xdiff > 0 and ydiff > 0:
width_zoom = math.log(360 / xdiff, 2)
height_zoom = math.log(360 / ydiff, 2)
zoom = math.ceil(min(width_zoom, height_zoom))

self.zoom = zoom
self.center_x = center_x
self.center_y = center_y
try:
self.zoom = zoom
self.center_x = center_x
self.center_y = center_y
except BaseException:
pass

def download_links(self):
"""assemble download links for pycsw"""
Expand Down
116 changes: 116 additions & 0 deletions geonode/geoserver/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -1783,6 +1783,122 @@ def _render_thumbnail(req_body, width=240, height=180):
return content


def _prepare_thumbanil_body_from_opts(request_body):
import mercantile
from geonode.utils import (_v,
bbox_to_projection,
bounds_to_zoom_level)
# Defaults
_img_src_template = """<img src='{ogc_location}'
style='width: {width}px; height: {height}px;
left: {left}px; top: {top}px;
opacity: 1; visibility: inherit; position: absolute;'/>\n"""

def decimal_encode(bbox):
import decimal
_bbox = []
for o in [float(coord) for coord in bbox]:
if isinstance(o, decimal.Decimal):
o = (str(o) for o in [o])
_bbox.append(o)
# Must be in the form : [x0, x1, y0, y1
return [_bbox[0], _bbox[2], _bbox[1], _bbox[3]]

# Sanity Checks
if 'bbox' not in request_body:
return None
if 'srid' not in request_body:
return None
for coord in request_body['bbox']:
if not coord:
return None

width = 240
if 'width' in request_body:
width = request_body['width']
height = 200
if 'height' in request_body:
height = request_body['height']
smurl = None
if 'smurl' in request_body:
smurl = request_body['smurl']
if not smurl and getattr(settings, 'THUMBNAIL_GENERATOR_DEFAULT_BG', None):
smurl = settings.THUMBNAIL_GENERATOR_DEFAULT_BG

layers = None
thumbnail_create_url = None
if 'thumbnail_create_url' in request_body:
thumbnail_create_url = request_body['thumbnail_create_url']
elif 'layers' in request_body:
layers = request_body['layers']

wms_endpoint = getattr(ogc_server_settings, "WMS_ENDPOINT") or 'ows'
wms_version = getattr(ogc_server_settings, "WMS_VERSION") or '1.1.1'
wms_format = getattr(ogc_server_settings, "WMS_FORMAT") or 'image/png8'

params = {
'service': 'WMS',
'version': wms_version,
'request': 'GetMap',
'layers': layers,
'format': wms_format,
# 'TIME': '-99999999999-01-01T00:00:00.0Z/99999999999-01-01T00:00:00.0Z'
}
_p = "&".join("%s=%s" % item for item in params.items())

import posixpath
thumbnail_create_url = posixpath.join(
ogc_server_settings.LOCATION,
wms_endpoint) + "?" + _p

# Compute Bounds
wgs84_bbox = decimal_encode(
bbox_to_projection([float(coord) for coord in request_body['bbox']] + [request_body['srid'], ],
target_srid=4326)[:4])

# Build Image Request Template
_img_request_template = "<div style='overflow: hidden; position:absolute; \
top:0px; left:0px; height: {height}px; width: {width}px;'> \
\n".format(height=height, width=width)

# Fetch XYZ tiles
bounds = wgs84_bbox[0:4]
zoom = bounds_to_zoom_level(bounds, width, height)

t_ll = mercantile.tile(_v(bounds[0], x=True), _v(bounds[1], x=False), zoom, truncate=True)
t_ur = mercantile.tile(_v(bounds[2], x=True), _v(bounds[3], x=False), zoom, truncate=True)
xmin, ymax = t_ll.x, t_ll.y
xmax, ymin = t_ur.x, t_ur.y

for xtile in range(xmin, xmax+1):
for ytile in range(ymin, ymax+1):
box = [(xtile-xmin)*256, (ytile-ymin)*255]
if smurl:
imgurl = smurl.format(z=zoom, x=xtile, y=ytile)
_img_request_template += _img_src_template.format(ogc_location=imgurl,
height=256, width=256,
left=box[0], top=box[1])

xy_bounds = mercantile.xy_bounds(mercantile.Tile(xtile, ytile, zoom))
params = {
'width': 256,
'height': 256,
'transparent': True,
'bbox': ",".join([str(xy_bounds.left), str(xy_bounds.bottom),
str(xy_bounds.right), str(xy_bounds.top)]),
'crs': 'EPSG:3857'
}
_p = "&".join("%s=%s" % item for item in params.items())

_img_request_template += \
_img_src_template.format(ogc_location=(thumbnail_create_url + '&' + _p),
height=256, width=256,
left=box[0], top=box[1])
_img_request_template += "</div>"
image = _render_thumbnail(_img_request_template, width=width, height=height)
return image


def _fixup_ows_url(thumb_spec):
# @HACK - for whatever reason, a map's maplayers ows_url contains only /geoserver/wms
# so rendering of thumbnails fails - replace those uri's with full geoserver URL
Expand Down
4 changes: 2 additions & 2 deletions geonode/geoserver/signals.py
Original file line number Diff line number Diff line change
Expand Up @@ -496,7 +496,7 @@ def command_url(command):
if not ('update_fields' in kwargs and kwargs['update_fields'] is not None and
'thumbnail_url' in kwargs['update_fields']):
logger.info("... Creating Thumbnail for Layer [%s]" % (instance.alternate))
create_gs_thumbnail(instance, overwrite=False)
create_gs_thumbnail(instance, overwrite=True)

legend_url = ogc_server_settings.PUBLIC_LOCATION + \
'wms?request=GetLegendGraphic&format=image/png&WIDTH=20&HEIGHT=20&LAYER=' + \
Expand Down Expand Up @@ -617,4 +617,4 @@ def geoserver_pre_save_maplayer(instance, sender, **kwargs):

def geoserver_post_save_map(instance, sender, **kwargs):
instance.set_missing_info()
create_gs_thumbnail(instance, overwrite=False)
create_gs_thumbnail(instance, overwrite=True)
15 changes: 10 additions & 5 deletions geonode/geoserver/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -496,11 +496,16 @@ def strip_prefix(path, prefix):
posixpath.join(workspace, layername, downstream_path, path))

if downstream_path in ('rest/styles') and len(request.body) > 0:
# Lets try
# http://localhost:8080/geoserver/rest/workspaces/<ws>/styles/<style>.xml
_url = str("".join([ogc_server_settings.LOCATION,
'rest/workspaces/', ws, '/styles',
path]))
if ws:
# Lets try
# http://localhost:8080/geoserver/rest/workspaces/<ws>/styles/<style>.xml
_url = str("".join([ogc_server_settings.LOCATION,
'rest/workspaces/', ws, '/styles',
path]))
else:
_url = str("".join([ogc_server_settings.LOCATION,
'rest/styles',
path]))
raw_url = _url

if downstream_path in 'ows' and (
Expand Down
92 changes: 17 additions & 75 deletions geonode/layers/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,8 @@
from geonode.layers.metadata import set_metadata
from geonode.utils import (http_client, check_ogc_backend,
unzip_file, extract_tarfile)
from ..geoserver.helpers import ogc_server_settings # set_layer_style
from ..geoserver.helpers import (ogc_server_settings,
_prepare_thumbanil_body_from_opts)

import tarfile

Expand All @@ -63,11 +64,6 @@

_separator = '\n' + ('-' * 100) + '\n'

_img_src_template = """<img src='{ogc_location}'
style='width: {width}px; height: {height}px;
left: {left}px; top: {top}px;
opacity: 1; visibility: inherit; position: absolute;'/>\n"""


def _clean_string(
str,
Expand Down Expand Up @@ -886,9 +882,7 @@ def upload(incoming, user=None, overwrite=False,

def create_thumbnail(instance, thumbnail_remote_url, thumbnail_create_url=None,
check_bbox=False, ogc_client=None, overwrite=False,
width=240, height=200, smurl=None):
if not smurl and getattr(settings, 'THUMBNAIL_GENERATOR_DEFAULT_BG', None):
smurl = settings.THUMBNAIL_GENERATOR_DEFAULT_BG
width=240, height=200):
thumbnail_dir = os.path.join(settings.MEDIA_ROOT, 'thumbs')
if not os.path.exists(thumbnail_dir):
os.makedirs(thumbnail_dir)
Expand Down Expand Up @@ -964,72 +958,20 @@ def create_thumbnail(instance, thumbnail_remote_url, thumbnail_create_url=None,
# Replace error message with None.
image = None
elif check_ogc_backend(geoserver.BACKEND_PACKAGE) and instance.bbox:
import mercantile
from geonode.geoserver.helpers import _render_thumbnail
from geonode.utils import (_v,
bbox_to_projection,
bounds_to_zoom_level)

def decimal_encode(bbox):
import decimal
_bbox = []
for o in [float(coord) for coord in bbox]:
if isinstance(o, decimal.Decimal):
o = (str(o) for o in [o])
_bbox.append(o)
# Must be in the form : [x0, x1, y0, y1
return [_bbox[0], _bbox[2], _bbox[1], _bbox[3]]

layer_bbox = instance.bbox[0:4]
# Sanity Checks
for coord in layer_bbox:
if not coord:
return

wgs84_bbox = decimal_encode(
bbox_to_projection([float(coord) for coord in layer_bbox] + [instance.srid, ],
target_srid=4326)[:4])

# Build Image Request Template
_img_request_template = "<div style='overflow: hidden; position:absolute; \
top:0px; left:0px; height: {height}px; width: {width}px;'> \
\n".format(height=height, width=width)

# Fetch XYZ tiles
bounds = wgs84_bbox[0:4]
zoom = bounds_to_zoom_level(bounds, width, height)

t_ll = mercantile.tile(_v(bounds[0], x=True), _v(bounds[1], x=False), zoom, truncate=True)
t_ur = mercantile.tile(_v(bounds[2], x=True), _v(bounds[3], x=False), zoom, truncate=True)
xmin, ymax = t_ll.x, t_ll.y
xmax, ymin = t_ur.x, t_ur.y

for xtile in range(xmin, xmax+1):
for ytile in range(ymin, ymax+1):
box = [(xtile-xmin)*256, (ytile-ymin)*255]
if smurl:
imgurl = smurl.format(z=zoom, x=xtile, y=ytile)
_img_request_template += _img_src_template.format(ogc_location=imgurl,
height=256, width=256,
left=box[0], top=box[1])

xy_bounds = mercantile.xy_bounds(mercantile.Tile(xtile, ytile, zoom))
params = {
'width': 256,
'height': 256,
'transparent': True,
'bbox': ",".join([str(xy_bounds.left), str(xy_bounds.bottom),
str(xy_bounds.right), str(xy_bounds.top)]),
'crs': 'EPSG:3857'
}
_p = "&".join("%s=%s" % item for item in params.items())

_img_request_template += \
_img_src_template.format(ogc_location=(thumbnail_create_url + '&' + _p),
height=256, width=256,
left=box[0], top=box[1])
_img_request_template += "</div>"
image = _render_thumbnail(_img_request_template, width=width, height=height)
instance_bbox = instance.bbox[0:4]
request_body = {
'bbox': [str(coord) for coord in instance_bbox],
'srid': instance.srid,
'width': width,
'height': height
}

if thumbnail_create_url:
request_body['thumbnail_create_url'] = thumbnail_create_url
elif instance.alternate:
request_body['layers'] = instance.alternate,

image = _prepare_thumbanil_body_from_opts(request_body)

if image is not None:
instance.save_thumbnail(thumbnail_name, image=image)
Expand Down

0 comments on commit 0f7cd61

Please sign in to comment.