Skip to content

Commit

Permalink
thumbnails: correctly use zoom value if specified (#3487)
Browse files Browse the repository at this point in the history
  • Loading branch information
fm3 authored Nov 22, 2018
1 parent 2c68652 commit 6f1e527
Show file tree
Hide file tree
Showing 5 changed files with 13 additions and 11 deletions.
2 changes: 1 addition & 1 deletion app/controllers/DataSetController.scala
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ class DataSetController @Inject()(userService: UserService,
val defaultCenterOpt = dataSet.defaultConfiguration.flatMap(c =>
c.configuration.get("position").flatMap(jsValue => JsonHelper.jsResultToOpt(jsValue.validate[Point3D])))
val defaultZoomOpt = dataSet.defaultConfiguration.flatMap(c =>
c.configuration.get("zoom").flatMap(jsValue => JsonHelper.jsResultToOpt(jsValue.validate[Int])))
c.configuration.get("zoom").flatMap(jsValue => JsonHelper.jsResultToOpt(jsValue.validate[Double])))
dataSetService
.clientFor(dataSet)
.flatMap(
Expand Down
2 changes: 1 addition & 1 deletion app/models/binary/DataStoreRpcClient.scala
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ class DataStoreRpcClient(dataStore: DataStore, dataSet: DataSet, rpc: RPC)(impli
dataLayerName: String,
width: Int,
height: Int,
zoom: Option[Int],
zoom: Option[Double],
center: Option[Point3D]): Fox[Array[Byte]] = {
logger.debug(s"Thumbnail called for: $organizationName-${dataSet.name} Layer: $dataLayerName")
rpc(s"${dataStore.url}/data/datasets/${urlEncode(organizationName)}/${dataSet.urlEncodedName}/layers/$dataLayerName/thumbnail.json")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,7 @@ class BinaryDataController @Inject()(
centerX: Option[Int],
centerY: Option[Int],
centerZ: Option[Int],
zoom: Option[Int]) = Action.async(parse.raw) {
zoom: Option[Double]) = Action.async(parse.raw) {
implicit request =>
accessTokenService.validateAccess(UserAccessRequest.readDataSources(DataSourceId(dataSetName, organizationName))) {
AllowRemoteOrigin {
Expand Down Expand Up @@ -259,7 +259,7 @@ class BinaryDataController @Inject()(
centerX: Option[Int],
centerY: Option[Int],
centerZ: Option[Int],
zoom: Option[Int]
zoom: Option[Double]
) = Action.async(parse.raw) {
implicit request =>
accessTokenService.validateAccess(UserAccessRequest.readDataSources(DataSourceId(dataSetName, organizationName))) {
Expand Down Expand Up @@ -352,7 +352,7 @@ class BinaryDataController @Inject()(
centerX: Option[Int],
centerY: Option[Int],
centerZ: Option[Int],
zoom: Option[Int]
zoom: Option[Double]
)(implicit m: MessagesProvider): Fox[(OutputStream) => Unit] = {
for {
(dataSource, dataLayer) <- getDataSourceAndDataLayer(organizationName, dataSetName, dataLayerName)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,15 @@ case class ImageThumbnail(mimeType: String, value: String)
object ImageThumbnail {
implicit val imageThumbnailFormat = Json.format[ImageThumbnail]

def bestResolutionExponent(dataLayer: DataLayerLike, width: Int, height: Int): Int = {
def bestResolutionExponent(dataLayer: DataLayerLike, width: Int, height: Int, zoom: Option[Double]): Int = {
// We want to make sure that the thumbnail only contains data, as much as possible but no black border
// To make sure there is no black border we are going to go with the second best resolution (hence the `- 1`)
val wr = math.floor(math.log(dataLayer.boundingBox.width.toDouble / width) / math.log(2)).toInt - 1
val hr = math.floor(math.log(dataLayer.boundingBox.height.toDouble / height) / math.log(2)).toInt - 1
val wr_zoom = zoom.map(z => math.floor(math.log(z / width) / math.log(2)).toInt - 1).getOrElse(Int.MaxValue)
val hr_zoom = zoom.map(z => math.floor(math.log(z / height) / math.log(2)).toInt - 1).getOrElse(Int.MaxValue)

math.max(0, List(wr, hr, dataLayer.resolutions.size - 1).min)
math.max(0, List(wr, hr, wr_zoom, hr_zoom, dataLayer.resolutions.size - 1).min)
}

def goodThumbnailParameters(dataLayer: DataLayerLike,
Expand All @@ -24,13 +26,13 @@ object ImageThumbnail {
centerX: Option[Int] = None,
centerY: Option[Int] = None,
centerZ: Option[Int] = None,
zoom: Option[Int] = None): VoxelPosition = {
zoomOpt: Option[Double] = None): VoxelPosition = {

// Parameters that seem to be working good enough
val center = if (centerX.isDefined && centerY.isDefined && centerZ.isDefined)
Point3D(centerX.get, centerY.get, centerZ.get)
else dataLayer.boundingBox.center
val resolutionExponent = zoom.getOrElse(bestResolutionExponent(dataLayer, width, height))
val resolutionExponent = bestResolutionExponent(dataLayer, width, height, zoomOpt)
val resolution = dataLayer.lookUpResolution(resolutionExponent, snapToClosest = true)
val x = Math.max(0, center.x - width * resolution.x / 2)
val y = Math.max(0, center.y - height * resolution.y / 2)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ GET /datasets/:organizationName/:dataSetName/layers/:dataLayerName/data
GET /datasets/:organizationName/:dataSetName/layers/:dataLayerName/data @com.scalableminds.webknossos.datastore.controllers.BinaryDataController.requestViaAjaxDebug(organizationName: String, dataSetName: String, dataLayerName: String, cubeSize: Int, x: Int, y: Int, z: Int, resolution: Int, halfByte: Boolean ?= false)
GET /datasets/:organizationName/:dataSetName/layers/:dataLayerName/sprite @com.scalableminds.webknossos.datastore.controllers.BinaryDataController.requestSpriteSheet(organizationName: String, dataSetName: String, dataLayerName: String, cubeSize: Int ?=128, imagesPerRow: Int ?= 8, x: Int, y: Int, z: Int, resolution: Int, halfByte: Boolean ?= false)
GET /datasets/:organizationName/:dataSetName/layers/:dataLayerName/image.jpg @com.scalableminds.webknossos.datastore.controllers.BinaryDataController.requestImage(organizationName: String, dataSetName: String, dataLayerName: String, width: Int, height: Int, x: Int, y: Int, z: Int, resolution: Int, halfByte: Boolean ?= false, blackAndWhite: Boolean ?= false)
GET /datasets/:organizationName/:dataSetName/layers/:dataLayerName/thumbnail.json @com.scalableminds.webknossos.datastore.controllers.BinaryDataController.requestImageThumbnailJson(organizationName: String, dataSetName: String, dataLayerName: String, width: Int, height: Int, centerX: Option[Int], centerY: Option[Int], centerZ: Option[Int], zoom: Option[Int])
GET /datasets/:organizationName/:dataSetName/layers/:dataLayerName/thumbnail.jpg @com.scalableminds.webknossos.datastore.controllers.BinaryDataController.requestImageThumbnailJpeg(organizationName: String, dataSetName: String, dataLayerName: String, width: Int, height: Int, centerX: Option[Int], centerY: Option[Int], centerZ: Option[Int], zoom: Option[Int])
GET /datasets/:organizationName/:dataSetName/layers/:dataLayerName/thumbnail.json @com.scalableminds.webknossos.datastore.controllers.BinaryDataController.requestImageThumbnailJson(organizationName: String, dataSetName: String, dataLayerName: String, width: Int, height: Int, centerX: Option[Int], centerY: Option[Int], centerZ: Option[Int], zoom: Option[Double])
GET /datasets/:organizationName/:dataSetName/layers/:dataLayerName/thumbnail.jpg @com.scalableminds.webknossos.datastore.controllers.BinaryDataController.requestImageThumbnailJpeg(organizationName: String, dataSetName: String, dataLayerName: String, width: Int, height: Int, centerX: Option[Int], centerY: Option[Int], centerZ: Option[Int], zoom: Option[Double])

# Knossos compatibale routes
GET /datasets/:organizationName/:dataSetName/layers/:dataLayerName/mag:resolution/x:x/y:y/z:z/bucket.raw @com.scalableminds.webknossos.datastore.controllers.BinaryDataController.requestViaKnossos(organizationName: String, dataSetName: String, dataLayerName: String, resolution: Int, x: Int, y: Int, z: Int, cubeSize: Int)
Expand Down

0 comments on commit 6f1e527

Please sign in to comment.