From bc745f7cf2c839e217e392b7ba0c1c36679b3308 Mon Sep 17 00:00:00 2001 From: Chris Allan Date: Wed, 2 Aug 2017 13:29:44 +0100 Subject: [PATCH 1/6] Also support `webclient` version of this URL --- .../omero/ms/thumbnail/ThumbnailMicroserviceVerticle.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/java/com/glencoesoftware/omero/ms/thumbnail/ThumbnailMicroserviceVerticle.java b/src/main/java/com/glencoesoftware/omero/ms/thumbnail/ThumbnailMicroserviceVerticle.java index 16f4ccc..73bda17 100644 --- a/src/main/java/com/glencoesoftware/omero/ms/thumbnail/ThumbnailMicroserviceVerticle.java +++ b/src/main/java/com/glencoesoftware/omero/ms/thumbnail/ThumbnailMicroserviceVerticle.java @@ -98,6 +98,9 @@ public void start(Future future) { router.get( "/webclient/render_thumbnail/size/:longestSide/:imageId*") .handler(this::renderThumbnail); + router.get( + "/webclient/render_thumbnail/:imageId*") + .handler(this::renderThumbnail); router.get( "/webgateway/render_thumbnail/:imageId/:longestSide*") .handler(this::renderThumbnail); From edb4f24f98ec96515b9706065847578503afd254 Mon Sep 17 00:00:00 2001 From: Chris Allan Date: Tue, 8 Aug 2017 10:38:40 +0100 Subject: [PATCH 2/6] Support for providing rendering settings ID --- .../ThumbnailMicroserviceVerticle.java | 5 + .../ms/thumbnail/ThumbnailRequestHandler.java | 145 +++++++++++++++++- .../omero/ms/thumbnail/ThumbnailVerticle.java | 9 +- 3 files changed, 152 insertions(+), 7 deletions(-) diff --git a/src/main/java/com/glencoesoftware/omero/ms/thumbnail/ThumbnailMicroserviceVerticle.java b/src/main/java/com/glencoesoftware/omero/ms/thumbnail/ThumbnailMicroserviceVerticle.java index 73bda17..0a74a4b 100644 --- a/src/main/java/com/glencoesoftware/omero/ms/thumbnail/ThumbnailMicroserviceVerticle.java +++ b/src/main/java/com/glencoesoftware/omero/ms/thumbnail/ThumbnailMicroserviceVerticle.java @@ -21,6 +21,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.stream.Collectors; import org.slf4j.LoggerFactory; @@ -149,6 +150,10 @@ private void renderThumbnail(RoutingContext event) { data.put("longestSide", Integer.parseInt(longestSide)); data.put("imageId", imageId); data.put("omeroSessionKey", event.get("omero.session_key")); + data.put("renderingDefId", + Optional.ofNullable(request.getParam("rdefId")) + .map(Long::parseLong) + .orElse(null)); vertx.eventBus().send( ThumbnailVerticle.RENDER_THUMBNAIL_EVENT, diff --git a/src/main/java/com/glencoesoftware/omero/ms/thumbnail/ThumbnailRequestHandler.java b/src/main/java/com/glencoesoftware/omero/ms/thumbnail/ThumbnailRequestHandler.java index 6baa134..62a7eed 100644 --- a/src/main/java/com/glencoesoftware/omero/ms/thumbnail/ThumbnailRequestHandler.java +++ b/src/main/java/com/glencoesoftware/omero/ms/thumbnail/ThumbnailRequestHandler.java @@ -18,10 +18,23 @@ package com.glencoesoftware.omero.ms.thumbnail; +import static omero.rtypes.rint; +import static omero.rtypes.unwrap; + import java.util.Arrays; +import java.util.HashMap; +import java.util.List; import java.util.Map; +import java.util.Optional; + +import org.perf4j.StopWatch; +import org.perf4j.slf4j.Slf4JStopWatch; +import org.slf4j.LoggerFactory; +import omero.ServerError; +import omero.api.ThumbnailStorePrx; import omero.model.Image; +import omero.sys.EventContext; /** * OMERO session aware handler whose event handler method conforms to the @@ -32,6 +45,31 @@ */ public class ThumbnailRequestHandler extends ThumbnailsRequestHandler { + private static final org.slf4j.Logger log = + LoggerFactory.getLogger(ThumbnailRequestHandler.class); + + /** + * {@link RenderingDef} identifier of the rendering settings to use when + * requesting the thumbnail. + */ + protected Optional renderingDefId; + + /** + * Default constructor with the ability to specify a rendering definition + * to use when requesting the thumbnail. + * @param longestSide Size to confine or upscale the longest side of the + * thumbnail to. The other side will then proportionately, based on aspect + * ratio, be scaled accordingly. + * @param imageId {@link Image} identifier to request a thumbnail for. + * @param renderingDefId {@link RenderingDef} identifier of the rendering + * settings to use. + */ + public ThumbnailRequestHandler( + int longestSide, long imageId, Optional renderingDefId) { + super(longestSide, Arrays.asList(imageId)); + this.renderingDefId = renderingDefId; + } + /** * Default constructor. * @param longestSide Size to confine or upscale the longest side of the @@ -48,11 +86,110 @@ public ThumbnailRequestHandler(int longestSide, long imageId) { * @return JPEG thumbnail byte array. */ public byte[] renderThumbnail(omero.client client) { - Map thumbnails = renderThumbnails(client); - if (thumbnails == null) { - return null; + try { + List images = getImages(client, imageIds); + if (images.size() == 1) { + return getThumbnail( + client, images.get(0), longestSide, renderingDefId); + } + log.debug("Cannot find any Image:{}", imageIds.get(0)); + } catch (Exception e) { + log.error("Exception while retrieving thumbnails", e); } - return thumbnails.get(imageIds.get(0)); + return null; } + /** + * Retrieves a JPEG thumbnail from the server. + * @param client OMERO client to use for thumbnail retrieval. + * @param image {@link Image} to retrieve thumbnail for. + * @param longestSide Size to confine or upscale the longest side of each + * thumbnail to. The other side will then proportionately, based on aspect + * ratio, be scaled accordingly. + * @param renderingDefId {@link RenderingDef} identifier of the rendering + * settings to use. May be null. + * @return JPEG thumbnail byte array. + * @throws ServerError If there was any sort of error retrieving the + * thumbnail. + */ + protected byte[] getThumbnail( + omero.client client, Image image, int longestSide, + Optional renderingDefId) + throws ServerError{ + ThumbnailStorePrx thumbnailStore = + client.getSession().createThumbnailStore(); + try { + Map ctx = new HashMap(); + long pixelsId = (Long) unwrap(image.getPrimaryPixels().getId()); + // Assume all the groups are the same + ctx.put( + "omero.group", + String.valueOf(unwrap( + image.getDetails().getGroup().getId())) + ); + + boolean hasRenderingSettings = + setPixelsId(ctx, thumbnailStore, pixelsId); + if (renderingDefId.isPresent()) { + Slf4JStopWatch t0 = new Slf4JStopWatch("setRenderingDefId"); + try { + thumbnailStore.setRenderingDefId(renderingDefId.get(), ctx); + } finally { + t0.stop(); + } + } + if (!hasRenderingSettings) { + // Operate as the object owner if we are an administrator + EventContext eventContext = + client.getSession().getAdminService().getEventContext(); + if (eventContext.memberOfGroups.contains(0)) { + ctx.put( + "omero.user", + String.valueOf(unwrap( + image.getDetails().getOwner().getId())) + ); + } + Slf4JStopWatch t0 = new Slf4JStopWatch("resetDefaults"); + try { + thumbnailStore.resetDefaults(); + } finally { + t0.stop(); + } + setPixelsId(ctx, thumbnailStore, pixelsId); + } + + Slf4JStopWatch t0 = new Slf4JStopWatch("getThumbnailByLongestSide"); + try { + return thumbnailStore.getThumbnailByLongestSide( + rint(longestSide), ctx); + } finally { + t0.stop(); + } + } finally { + thumbnailStore.close(); + } + } + + /** + * Sets the {@link Pixels} identifier on a thumbnail store in an + * instrumented fashion. + * @param ctx Calling context. + * @param thumbnailStore Thumbnail store to set pixelsId on. + * @param pixelsId {@link Pixels} identifier to set. + * @return true if a set of rendering settings is available + * for the {@link Pixels} object identified by pixelsId + * otherwise false + * @throws ServerError If there was any sort of error setting the + * identifier. + */ + private boolean setPixelsId( + Map ctx, ThumbnailStorePrx thumbnailStore, + long pixelsId) throws ServerError { + StopWatch t0 = new Slf4JStopWatch("setPixelsId"); + try { + return thumbnailStore.setPixelsId(pixelsId, ctx); + } finally { + t0.stop(); + } + } } diff --git a/src/main/java/com/glencoesoftware/omero/ms/thumbnail/ThumbnailVerticle.java b/src/main/java/com/glencoesoftware/omero/ms/thumbnail/ThumbnailVerticle.java index 71044fd..192eecc 100644 --- a/src/main/java/com/glencoesoftware/omero/ms/thumbnail/ThumbnailVerticle.java +++ b/src/main/java/com/glencoesoftware/omero/ms/thumbnail/ThumbnailVerticle.java @@ -22,6 +22,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.Map.Entry; import org.slf4j.LoggerFactory; @@ -98,14 +99,16 @@ private void renderThumbnail(Message message) { String omeroSessionKey = data.getString("omeroSessionKey"); int longestSide = data.getInteger("longestSide"); long imageId = data.getLong("imageId"); + Optional renderingDefId = + Optional.ofNullable(data.getLong("renderingDefId")); log.debug( - "Render thumbnail request Image:{} longest side {}", - imageId, longestSide); + "Render thumbnail request Image:{} longest side {} RenderingDef:{}", + imageId, longestSide, renderingDefId.orElse(null)); try (OmeroRequest request = new OmeroRequest( host, port, omeroSessionKey)) { byte[] thumbnail = request.execute(new ThumbnailRequestHandler( - longestSide, imageId)::renderThumbnail); + longestSide, imageId, renderingDefId)::renderThumbnail); if (thumbnail == null) { message.fail(404, "Cannot find Image:" + imageId); } else { From f17b15db6efcc327ec1d914d14d912fcc7c715e1 Mon Sep 17 00:00:00 2001 From: Chris Allan Date: Tue, 8 Aug 2017 10:38:49 +0100 Subject: [PATCH 3/6] Fix documentation typo --- .../omero/ms/thumbnail/ThumbnailsRequestHandler.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/glencoesoftware/omero/ms/thumbnail/ThumbnailsRequestHandler.java b/src/main/java/com/glencoesoftware/omero/ms/thumbnail/ThumbnailsRequestHandler.java index c689627..7f1f3fb 100644 --- a/src/main/java/com/glencoesoftware/omero/ms/thumbnail/ThumbnailsRequestHandler.java +++ b/src/main/java/com/glencoesoftware/omero/ms/thumbnail/ThumbnailsRequestHandler.java @@ -87,7 +87,7 @@ public Map renderThumbnails(omero.client client) { } /** - * Retrieves a single {@link Image} from the server. + * Retrieves a list of loaded {@link Image}s from the server. * @param client OMERO client to use for querying. * @param imageIds {@link Image} identifiers to query for. * @return List of loaded {@link Image} and primary {@link Pixels}. From 3660476da777b3699ef221acf0a137d3a51211b1 Mon Sep 17 00:00:00 2001 From: Chris Allan Date: Tue, 8 Aug 2017 10:43:45 +0100 Subject: [PATCH 4/6] Clean up argument parsing --- .../thumbnail/ThumbnailMicroserviceVerticle.java | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/glencoesoftware/omero/ms/thumbnail/ThumbnailMicroserviceVerticle.java b/src/main/java/com/glencoesoftware/omero/ms/thumbnail/ThumbnailMicroserviceVerticle.java index 0a74a4b..07354fd 100644 --- a/src/main/java/com/glencoesoftware/omero/ms/thumbnail/ThumbnailMicroserviceVerticle.java +++ b/src/main/java/com/glencoesoftware/omero/ms/thumbnail/ThumbnailMicroserviceVerticle.java @@ -140,15 +140,14 @@ public void stop() throws Exception { * @param event Current routing context. */ private void renderThumbnail(RoutingContext event) { - HttpServerRequest request = event.request(); - final String longestSide = - request.getParam("longestSide") == null? "96" - : request.getParam("longestSide"); - final Long imageId = Long.parseLong(request.getParam("imageId")); + final HttpServerRequest request = event.request(); final HttpServerResponse response = event.response(); - Map data = new HashMap(); - data.put("longestSide", Integer.parseInt(longestSide)); - data.put("imageId", imageId); + final Map data = new HashMap(); + data.put("longestSide", + Optional.ofNullable(request.getParam("longestSide")) + .map(Integer::parseInt) + .orElse(96)); + data.put("imageId", Long.parseLong(request.getParam("imageId"))); data.put("omeroSessionKey", event.get("omero.session_key")); data.put("renderingDefId", Optional.ofNullable(request.getParam("rdefId")) From 00bc1bddb7ce44acf32590af76c6967ad411a9b9 Mon Sep 17 00:00:00 2001 From: Chris Allan Date: Tue, 8 Aug 2017 10:44:00 +0100 Subject: [PATCH 5/6] Remove unused import --- .../omero/ms/thumbnail/ThumbnailMicroserviceVerticle.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/com/glencoesoftware/omero/ms/thumbnail/ThumbnailMicroserviceVerticle.java b/src/main/java/com/glencoesoftware/omero/ms/thumbnail/ThumbnailMicroserviceVerticle.java index 07354fd..27b1b40 100644 --- a/src/main/java/com/glencoesoftware/omero/ms/thumbnail/ThumbnailMicroserviceVerticle.java +++ b/src/main/java/com/glencoesoftware/omero/ms/thumbnail/ThumbnailMicroserviceVerticle.java @@ -42,7 +42,6 @@ import io.vertx.core.http.HttpServerResponse; import io.vertx.core.json.Json; import io.vertx.core.json.JsonObject; -import io.vertx.ext.web.Cookie; import io.vertx.ext.web.Router; import io.vertx.ext.web.RoutingContext; import io.vertx.ext.web.handler.CookieHandler; From 42a624951123a689be5f9b08e834c070840c5cf8 Mon Sep 17 00:00:00 2001 From: Chris Allan Date: Tue, 8 Aug 2017 11:45:57 +0100 Subject: [PATCH 6/6] Clean up argument parsing --- .../ThumbnailMicroserviceVerticle.java | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/src/main/java/com/glencoesoftware/omero/ms/thumbnail/ThumbnailMicroserviceVerticle.java b/src/main/java/com/glencoesoftware/omero/ms/thumbnail/ThumbnailMicroserviceVerticle.java index 27b1b40..5426af5 100644 --- a/src/main/java/com/glencoesoftware/omero/ms/thumbnail/ThumbnailMicroserviceVerticle.java +++ b/src/main/java/com/glencoesoftware/omero/ms/thumbnail/ThumbnailMicroserviceVerticle.java @@ -188,17 +188,18 @@ private void renderThumbnail(RoutingContext event) { * @param event Current routing context. */ private void getThumbnails(RoutingContext event) { - HttpServerRequest request = event.request(); - final String longestSide = - request.getParam("longestSide") == null? "96" - : request.getParam("longestSide"); - final List imageIds = request.params().getAll("id").stream() - .map(x -> Long.parseLong(x)) - .collect(Collectors.toList()); + final HttpServerRequest request = event.request(); final HttpServerResponse response = event.response(); - Map data = new HashMap(); - data.put("longestSide", Integer.parseInt(longestSide)); - data.put("imageIds", imageIds.toArray()); + final Map data = new HashMap(); + data.put("longestSide", + Optional.ofNullable(request.getParam("longestSide")) + .map(Integer::parseInt) + .orElse(96)); + data.put("imageIds", + request.params().getAll("id").stream() + .map(Long::parseLong) + .collect(Collectors.toList()) + .toArray()); data.put("omeroSessionKey", event.get("omero.session_key")); vertx.eventBus().send(