girder-large-image 1.23.3.dev31__tar.gz → 1.23.3.dev59__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {girder-large-image-1.23.3.dev31 → girder-large-image-1.23.3.dev59}/PKG-INFO +1 -1
- {girder-large-image-1.23.3.dev31 → girder-large-image-1.23.3.dev59}/girder_large_image/rest/tiles.py +70 -4
- {girder-large-image-1.23.3.dev31 → girder-large-image-1.23.3.dev59}/girder_large_image/web_client/views/imageViewerSelectWidget.js +8 -2
- {girder-large-image-1.23.3.dev31 → girder-large-image-1.23.3.dev59}/girder_large_image/web_client/vue/components/CompositeLayers.vue +30 -20
- {girder-large-image-1.23.3.dev31 → girder-large-image-1.23.3.dev59}/girder_large_image/web_client/vue/components/FrameSelector.vue +6 -2
- {girder-large-image-1.23.3.dev31 → girder-large-image-1.23.3.dev59}/girder_large_image/web_client/vue/components/PresetsMenu.vue +76 -35
- {girder-large-image-1.23.3.dev31 → girder-large-image-1.23.3.dev59}/girder_large_image.egg-info/PKG-INFO +1 -1
- {girder-large-image-1.23.3.dev31 → girder-large-image-1.23.3.dev59}/girder_large_image.egg-info/requires.txt +2 -2
- {girder-large-image-1.23.3.dev31 → girder-large-image-1.23.3.dev59}/test_girder/test_tiles_rest.py +27 -0
- {girder-large-image-1.23.3.dev31 → girder-large-image-1.23.3.dev59}/LICENSE +0 -0
- {girder-large-image-1.23.3.dev31 → girder-large-image-1.23.3.dev59}/README.rst +0 -0
- {girder-large-image-1.23.3.dev31 → girder-large-image-1.23.3.dev59}/girder_large_image/__init__.py +0 -0
- {girder-large-image-1.23.3.dev31 → girder-large-image-1.23.3.dev59}/girder_large_image/constants.py +0 -0
- {girder-large-image-1.23.3.dev31 → girder-large-image-1.23.3.dev59}/girder_large_image/girder_tilesource.py +0 -0
- {girder-large-image-1.23.3.dev31 → girder-large-image-1.23.3.dev59}/girder_large_image/loadmodelcache.py +0 -0
- {girder-large-image-1.23.3.dev31 → girder-large-image-1.23.3.dev59}/girder_large_image/models/__init__.py +0 -0
- {girder-large-image-1.23.3.dev31 → girder-large-image-1.23.3.dev59}/girder_large_image/models/image_item.py +0 -0
- {girder-large-image-1.23.3.dev31 → girder-large-image-1.23.3.dev59}/girder_large_image/rest/__init__.py +0 -0
- {girder-large-image-1.23.3.dev31 → girder-large-image-1.23.3.dev59}/girder_large_image/rest/item_meta.py +0 -0
- {girder-large-image-1.23.3.dev31 → girder-large-image-1.23.3.dev59}/girder_large_image/rest/large_image_resource.py +0 -0
- {girder-large-image-1.23.3.dev31 → girder-large-image-1.23.3.dev59}/girder_large_image/web_client/eventStream.js +0 -0
- {girder-large-image-1.23.3.dev31 → girder-large-image-1.23.3.dev59}/girder_large_image/web_client/extra/.gitignore +0 -0
- {girder-large-image-1.23.3.dev31 → girder-large-image-1.23.3.dev59}/girder_large_image/web_client/index.js +0 -0
- {girder-large-image-1.23.3.dev31 → girder-large-image-1.23.3.dev59}/girder_large_image/web_client/main.js +0 -0
- {girder-large-image-1.23.3.dev31 → girder-large-image-1.23.3.dev59}/girder_large_image/web_client/package.json +0 -0
- {girder-large-image-1.23.3.dev31 → girder-large-image-1.23.3.dev59}/girder_large_image/web_client/routes.js +0 -0
- {girder-large-image-1.23.3.dev31 → girder-large-image-1.23.3.dev59}/girder_large_image/web_client/stylesheets/fileList.styl +0 -0
- {girder-large-image-1.23.3.dev31 → girder-large-image-1.23.3.dev59}/girder_large_image/web_client/stylesheets/imageViewerSelectWidget.styl +0 -0
- {girder-large-image-1.23.3.dev31 → girder-large-image-1.23.3.dev59}/girder_large_image/web_client/stylesheets/itemList.styl +0 -0
- {girder-large-image-1.23.3.dev31 → girder-large-image-1.23.3.dev59}/girder_large_image/web_client/stylesheets/itemView.styl +0 -0
- {girder-large-image-1.23.3.dev31 → girder-large-image-1.23.3.dev59}/girder_large_image/web_client/stylesheets/itemViewCodemirror.styl +0 -0
- {girder-large-image-1.23.3.dev31 → girder-large-image-1.23.3.dev59}/girder_large_image/web_client/stylesheets/largeImageConfig.styl +0 -0
- {girder-large-image-1.23.3.dev31 → girder-large-image-1.23.3.dev59}/girder_large_image/web_client/stylesheets/metadataWidget.styl +0 -0
- {girder-large-image-1.23.3.dev31 → girder-large-image-1.23.3.dev59}/girder_large_image/web_client/templates/imageViewerSelectWidget.pug +0 -0
- {girder-large-image-1.23.3.dev31 → girder-large-image-1.23.3.dev59}/girder_large_image/web_client/templates/itemList.pug +0 -0
- {girder-large-image-1.23.3.dev31 → girder-large-image-1.23.3.dev59}/girder_large_image/web_client/templates/itemView.pug +0 -0
- {girder-large-image-1.23.3.dev31 → girder-large-image-1.23.3.dev59}/girder_large_image/web_client/templates/itemViewCodemirror.pug +0 -0
- {girder-large-image-1.23.3.dev31 → girder-large-image-1.23.3.dev59}/girder_large_image/web_client/templates/largeImageConfig.pug +0 -0
- {girder-large-image-1.23.3.dev31 → girder-large-image-1.23.3.dev59}/girder_large_image/web_client/templates/largeImage_fileAction.pug +0 -0
- {girder-large-image-1.23.3.dev31 → girder-large-image-1.23.3.dev59}/girder_large_image/web_client/templates/metadataWidget.pug +0 -0
- {girder-large-image-1.23.3.dev31 → girder-large-image-1.23.3.dev59}/girder_large_image/web_client/templates/metadatumEditWidget.pug +0 -0
- {girder-large-image-1.23.3.dev31 → girder-large-image-1.23.3.dev59}/girder_large_image/web_client/views/configView.js +0 -0
- {girder-large-image-1.23.3.dev31 → girder-large-image-1.23.3.dev59}/girder_large_image/web_client/views/fileList.js +0 -0
- {girder-large-image-1.23.3.dev31 → girder-large-image-1.23.3.dev59}/girder_large_image/web_client/views/imageViewerWidget/base.js +0 -0
- {girder-large-image-1.23.3.dev31 → girder-large-image-1.23.3.dev59}/girder_large_image/web_client/views/imageViewerWidget/geojs.js +0 -0
- {girder-large-image-1.23.3.dev31 → girder-large-image-1.23.3.dev59}/girder_large_image/web_client/views/imageViewerWidget/index.js +0 -0
- {girder-large-image-1.23.3.dev31 → girder-large-image-1.23.3.dev59}/girder_large_image/web_client/views/imageViewerWidget/leaflet.js +0 -0
- {girder-large-image-1.23.3.dev31 → girder-large-image-1.23.3.dev59}/girder_large_image/web_client/views/imageViewerWidget/openlayers.js +0 -0
- {girder-large-image-1.23.3.dev31 → girder-large-image-1.23.3.dev59}/girder_large_image/web_client/views/imageViewerWidget/openseadragon.js +0 -0
- {girder-large-image-1.23.3.dev31 → girder-large-image-1.23.3.dev59}/girder_large_image/web_client/views/imageViewerWidget/setFrameQuad.js +0 -0
- {girder-large-image-1.23.3.dev31 → girder-large-image-1.23.3.dev59}/girder_large_image/web_client/views/imageViewerWidget/slideatlas.js +0 -0
- {girder-large-image-1.23.3.dev31 → girder-large-image-1.23.3.dev59}/girder_large_image/web_client/views/index.js +0 -0
- {girder-large-image-1.23.3.dev31 → girder-large-image-1.23.3.dev59}/girder_large_image/web_client/views/itemList.js +0 -0
- {girder-large-image-1.23.3.dev31 → girder-large-image-1.23.3.dev59}/girder_large_image/web_client/views/itemView.js +0 -0
- {girder-large-image-1.23.3.dev31 → girder-large-image-1.23.3.dev59}/girder_large_image/web_client/views/itemViewCodemirror.js +0 -0
- {girder-large-image-1.23.3.dev31 → girder-large-image-1.23.3.dev59}/girder_large_image/web_client/views/itemViewWidget.js +0 -0
- {girder-large-image-1.23.3.dev31 → girder-large-image-1.23.3.dev59}/girder_large_image/web_client/views/metadataWidget.js +0 -0
- {girder-large-image-1.23.3.dev31 → girder-large-image-1.23.3.dev59}/girder_large_image/web_client/vue/components/DualInput.vue +0 -0
- {girder-large-image-1.23.3.dev31 → girder-large-image-1.23.3.dev59}/girder_large_image/web_client/vue/components/HistogramEditor.vue +0 -0
- {girder-large-image-1.23.3.dev31 → girder-large-image-1.23.3.dev59}/girder_large_image/web_client/vue/utils/clamp.js +0 -0
- {girder-large-image-1.23.3.dev31 → girder-large-image-1.23.3.dev59}/girder_large_image/web_client/vue/utils/colors.js +0 -0
- {girder-large-image-1.23.3.dev31 → girder-large-image-1.23.3.dev59}/girder_large_image/web_client/vue/utils/drag.js +0 -0
- {girder-large-image-1.23.3.dev31 → girder-large-image-1.23.3.dev59}/girder_large_image/web_client/webpack.helper.js +0 -0
- {girder-large-image-1.23.3.dev31 → girder-large-image-1.23.3.dev59}/girder_large_image.egg-info/SOURCES.txt +0 -0
- {girder-large-image-1.23.3.dev31 → girder-large-image-1.23.3.dev59}/girder_large_image.egg-info/dependency_links.txt +0 -0
- {girder-large-image-1.23.3.dev31 → girder-large-image-1.23.3.dev59}/girder_large_image.egg-info/entry_points.txt +0 -0
- {girder-large-image-1.23.3.dev31 → girder-large-image-1.23.3.dev59}/girder_large_image.egg-info/not-zip-safe +0 -0
- {girder-large-image-1.23.3.dev31 → girder-large-image-1.23.3.dev59}/girder_large_image.egg-info/top_level.txt +0 -0
- {girder-large-image-1.23.3.dev31 → girder-large-image-1.23.3.dev59}/setup.cfg +0 -0
- {girder-large-image-1.23.3.dev31 → girder-large-image-1.23.3.dev59}/setup.py +0 -0
- {girder-large-image-1.23.3.dev31 → girder-large-image-1.23.3.dev59}/test_girder/__init__.py +0 -0
- {girder-large-image-1.23.3.dev31 → girder-large-image-1.23.3.dev59}/test_girder/conftest.py +0 -0
- {girder-large-image-1.23.3.dev31 → girder-large-image-1.23.3.dev59}/test_girder/girder_utilities.py +0 -0
- {girder-large-image-1.23.3.dev31 → girder-large-image-1.23.3.dev59}/test_girder/test_large_image.py +0 -0
- {girder-large-image-1.23.3.dev31 → girder-large-image-1.23.3.dev59}/test_girder/test_web_client.py +0 -0
- {girder-large-image-1.23.3.dev31 → girder-large-image-1.23.3.dev59}/test_girder/web_client_specs/.eslintrc +0 -0
- {girder-large-image-1.23.3.dev31 → girder-large-image-1.23.3.dev59}/test_girder/web_client_specs/imageViewerSpec.js +0 -0
- {girder-large-image-1.23.3.dev31 → girder-large-image-1.23.3.dev59}/test_girder/web_client_specs/largeImageSpec.js +0 -0
- {girder-large-image-1.23.3.dev31 → girder-large-image-1.23.3.dev59}/test_girder/web_client_specs/otherFeatures.js +0 -0
{girder-large-image-1.23.3.dev31 → girder-large-image-1.23.3.dev59}/girder_large_image/rest/tiles.py
RENAMED
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
#############################################################################
|
|
16
16
|
|
|
17
17
|
import hashlib
|
|
18
|
+
import io
|
|
18
19
|
import math
|
|
19
20
|
import os
|
|
20
21
|
import pathlib
|
|
@@ -33,6 +34,7 @@ from girder.constants import AccessType, TokenScope
|
|
|
33
34
|
from girder.exceptions import RestException
|
|
34
35
|
from girder.models.file import File
|
|
35
36
|
from girder.models.item import Item
|
|
37
|
+
from girder.models.upload import Upload
|
|
36
38
|
from girder.utility.progress import setResponseTimeLimit
|
|
37
39
|
from large_image.cache_util import strhash
|
|
38
40
|
from large_image.constants import TileInputUnits, TileOutputMimeTypes
|
|
@@ -150,6 +152,7 @@ class TilesItemResource(ItemResource):
|
|
|
150
152
|
apiRoot.item.route('GET', (':itemId', 'tiles', 'thumbnail'), self.getTilesThumbnail)
|
|
151
153
|
apiRoot.item.route('GET', (':itemId', 'tiles', 'thumbnails'), self.listTilesThumbnails)
|
|
152
154
|
apiRoot.item.route('DELETE', (':itemId', 'tiles', 'thumbnails'), self.deleteTilesThumbnails)
|
|
155
|
+
apiRoot.item.route('POST', (':itemId', 'tiles', 'thumbnails'), self.addTilesThumbnails)
|
|
153
156
|
apiRoot.item.route('GET', (':itemId', 'tiles', 'region'), self.getTilesRegion)
|
|
154
157
|
apiRoot.item.route('GET', (':itemId', 'tiles', 'tile_frames'), self.tileFrames)
|
|
155
158
|
apiRoot.item.route('GET', (':itemId', 'tiles', 'tile_frames', 'quad_info'),
|
|
@@ -1429,11 +1432,74 @@ class TilesItemResource(ItemResource):
|
|
|
1429
1432
|
@autoDescribeRoute(
|
|
1430
1433
|
Description('Delete thumbnail and data files associated with a large_image item.')
|
|
1431
1434
|
.modelParam('itemId', model=Item, level=AccessType.READ)
|
|
1432
|
-
.param('keep', 'Number of thumbnails to keep.
|
|
1433
|
-
required=False,
|
|
1435
|
+
.param('keep', 'Number of thumbnails to keep. Ignored if a key is '
|
|
1436
|
+
'specified.', dataType='integer', required=False,
|
|
1437
|
+
default=10000)
|
|
1438
|
+
.param('key', 'A specific key to delete', required=False)
|
|
1439
|
+
.param('thumbnail', 'If a key is specified, true if the key is a '
|
|
1440
|
+
'thumbnail; false if the key is a data record',
|
|
1441
|
+
dataType='boolean', required=False)
|
|
1434
1442
|
.errorResponse('ID was invalid.')
|
|
1435
1443
|
.errorResponse('Read access was denied for the item.', 403)
|
|
1436
1444
|
)
|
|
1437
1445
|
@access.admin(scope=TokenScope.DATA_WRITE)
|
|
1438
|
-
def deleteTilesThumbnails(self, item, keep):
|
|
1439
|
-
|
|
1446
|
+
def deleteTilesThumbnails(self, item, keep, key=None, thumbnail=True):
|
|
1447
|
+
if not key:
|
|
1448
|
+
return self.imageItemModel.removeThumbnailFiles(item, keep=keep or 0)
|
|
1449
|
+
thumbnail = str(thumbnail).lower() != 'false'
|
|
1450
|
+
query = {
|
|
1451
|
+
'attachedToType': 'item',
|
|
1452
|
+
'attachedToId': item['_id'],
|
|
1453
|
+
'isLargeImageThumbnail' if thumbnail is not False else 'isLargeImageData': True,
|
|
1454
|
+
'thumbnailKey': key,
|
|
1455
|
+
}
|
|
1456
|
+
file = File().findOne(query)
|
|
1457
|
+
if file:
|
|
1458
|
+
File().remove(file)
|
|
1459
|
+
return [file]
|
|
1460
|
+
|
|
1461
|
+
@autoDescribeRoute(
|
|
1462
|
+
Description('Associate or replace a thumbnail or data file with a large_image items.')
|
|
1463
|
+
.responseClass('File')
|
|
1464
|
+
.modelParam('itemId', model=Item, level=AccessType.WRITE)
|
|
1465
|
+
.param('key', 'A specific key to delete', required=True)
|
|
1466
|
+
.param('thumbnail', 'If a key is specified, true if the key is a '
|
|
1467
|
+
'thumbnail; false if the key is a data record',
|
|
1468
|
+
dataType='boolean', required=False)
|
|
1469
|
+
.param('mimeType', 'The MIME type of the file.', required=False)
|
|
1470
|
+
.param('data', 'An image or data block to associated with the large_image item.',
|
|
1471
|
+
paramType='body', dataType='binary')
|
|
1472
|
+
.consumes('application/octet-stream')
|
|
1473
|
+
.errorResponse('ID was invalid.')
|
|
1474
|
+
.errorResponse('Read access was denied for the item.', 403)
|
|
1475
|
+
)
|
|
1476
|
+
@access.user(scope=TokenScope.DATA_WRITE)
|
|
1477
|
+
def addTilesThumbnails(self, item, key, mimeType, thumbnail=False, data=None):
|
|
1478
|
+
user = self.getCurrentUser()
|
|
1479
|
+
thumbnail = str(thumbnail).lower() != 'false'
|
|
1480
|
+
query = {
|
|
1481
|
+
'attachedToType': 'item',
|
|
1482
|
+
'attachedToId': item['_id'],
|
|
1483
|
+
'isLargeImageThumbnail' if thumbnail is not False else 'isLargeImageData': True,
|
|
1484
|
+
'thumbnailKey': key,
|
|
1485
|
+
}
|
|
1486
|
+
file = File().findOne(query)
|
|
1487
|
+
if file:
|
|
1488
|
+
File().remove(file)
|
|
1489
|
+
data = cherrypy.request.body.read()
|
|
1490
|
+
try:
|
|
1491
|
+
import magic
|
|
1492
|
+
mimeType = magic.from_buffer(data, mime=True) or mimeType
|
|
1493
|
+
except Exception:
|
|
1494
|
+
pass
|
|
1495
|
+
mimeType = mimeType or 'application/octet-stream'
|
|
1496
|
+
datafile = Upload().uploadFromFile(
|
|
1497
|
+
io.BytesIO(data), size=len(data),
|
|
1498
|
+
name='_largeImageThumbnail', parentType='item', parent=item,
|
|
1499
|
+
user=user, mimeType=mimeType, attachParent=True)
|
|
1500
|
+
datafile.update({
|
|
1501
|
+
'isLargeImageThumbnail' if thumbnail is not False else 'isLargeImageData': True,
|
|
1502
|
+
'thumbnailKey': key,
|
|
1503
|
+
})
|
|
1504
|
+
datafile = File().save(datafile)
|
|
1505
|
+
return datafile
|
|
@@ -47,7 +47,12 @@ var ImageViewerSelectWidget = View.extend({
|
|
|
47
47
|
this.itemId = settings.imageModel.id;
|
|
48
48
|
this.model = settings.imageModel;
|
|
49
49
|
this.currentViewer = null;
|
|
50
|
-
largeImageConfig.getSettings(() =>
|
|
50
|
+
largeImageConfig.getSettings(() => {
|
|
51
|
+
largeImageConfig.getConfigFile(this.model.get('folderId')).done((config) => {
|
|
52
|
+
this._liConfig = config || {};
|
|
53
|
+
this.render();
|
|
54
|
+
});
|
|
55
|
+
});
|
|
51
56
|
},
|
|
52
57
|
|
|
53
58
|
render: function () {
|
|
@@ -73,7 +78,8 @@ var ImageViewerSelectWidget = View.extend({
|
|
|
73
78
|
propsData: {
|
|
74
79
|
itemId: this.itemId,
|
|
75
80
|
imageMetadata: imageMetadata,
|
|
76
|
-
frameUpdate: frameUpdate
|
|
81
|
+
frameUpdate: frameUpdate,
|
|
82
|
+
liConfig: this._liConfig
|
|
77
83
|
}
|
|
78
84
|
});
|
|
79
85
|
this.vueApp = vm;
|
|
@@ -66,7 +66,6 @@ export default {
|
|
|
66
66
|
enabled: true,
|
|
67
67
|
min: undefined,
|
|
68
68
|
max: undefined,
|
|
69
|
-
custom: false,
|
|
70
69
|
autoRange: undefined
|
|
71
70
|
}
|
|
72
71
|
})
|
|
@@ -102,36 +101,45 @@ export default {
|
|
|
102
101
|
},
|
|
103
102
|
initializeStateFromStyle() {
|
|
104
103
|
this.enabledLayers = []
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
const
|
|
108
|
-
|
|
104
|
+
this.layers.forEach((layer) => {
|
|
105
|
+
const layerInfo = this.compositeLayerInfo[layer]
|
|
106
|
+
const currentLayerStyle = this.currentStyle.bands.find(
|
|
107
|
+
(s) => s.framedelta === layerInfo.framedelta
|
|
108
|
+
&& s.band === layerInfo.band
|
|
109
|
+
)
|
|
109
110
|
if (currentLayerStyle) {
|
|
110
|
-
this.enabledLayers.push(
|
|
111
|
+
this.enabledLayers.push(layer)
|
|
112
|
+
this.compositeLayerInfo[layer].enabled = true;
|
|
113
|
+
this.compositeLayerInfo[layer].palette = currentLayerStyle.palette;
|
|
111
114
|
if (
|
|
112
115
|
currentLayerStyle.min && currentLayerStyle.max
|
|
113
|
-
&& currentLayerStyle.min.includes("min:")
|
|
114
|
-
&& currentLayerStyle.max.includes("max:")
|
|
116
|
+
&& currentLayerStyle.min.toString().includes("min:")
|
|
117
|
+
&& currentLayerStyle.max.toString().includes("max:")
|
|
115
118
|
) {
|
|
116
|
-
|
|
117
|
-
currentLayerStyle.min.replace("min:", '')
|
|
119
|
+
this.compositeLayerInfo[layer].autoRange = parseFloat(
|
|
120
|
+
currentLayerStyle.min.toString().replace("min:", '')
|
|
118
121
|
) * 100
|
|
119
|
-
|
|
120
|
-
|
|
122
|
+
this.compositeLayerInfo[layer].min = undefined
|
|
123
|
+
this.compositeLayerInfo[layer].max = undefined
|
|
124
|
+
} else {
|
|
125
|
+
this.compositeLayerInfo[layer].autoRange = undefined
|
|
121
126
|
}
|
|
122
127
|
}
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
128
|
+
else {
|
|
129
|
+
this.compositeLayerInfo[layer].enabled = false;
|
|
130
|
+
this.compositeLayerInfo[layer].autoRange = undefined;
|
|
131
|
+
this.compositeLayerInfo[layer].min = undefined;
|
|
132
|
+
this.compositeLayerInfo[layer].max = undefined;
|
|
133
|
+
}
|
|
129
134
|
})
|
|
135
|
+
|
|
130
136
|
const autoRanges = Object.entries(this.compositeLayerInfo)
|
|
137
|
+
.filter(([index, info]) => info.enabled)
|
|
131
138
|
.map(([index, info]) => info.autoRange)
|
|
132
|
-
.filter((a) => a !== undefined)
|
|
133
139
|
if (autoRanges.every((v) => v === autoRanges[0])) {
|
|
134
140
|
this.autoRangeForAll = autoRanges[0]
|
|
141
|
+
} else {
|
|
142
|
+
this.autoRangeForAll = undefined
|
|
135
143
|
}
|
|
136
144
|
},
|
|
137
145
|
fetchCurrentFrameHistogram() {
|
|
@@ -285,7 +293,9 @@ export default {
|
|
|
285
293
|
}
|
|
286
294
|
},
|
|
287
295
|
currentStyle() {
|
|
288
|
-
this.
|
|
296
|
+
if(this.currentStyle.preset) {
|
|
297
|
+
this.initializeStateFromStyle()
|
|
298
|
+
}
|
|
289
299
|
}
|
|
290
300
|
}
|
|
291
301
|
}
|
|
@@ -5,7 +5,7 @@ import DualInput from './DualInput.vue';
|
|
|
5
5
|
import PresetsMenu from './PresetsMenu.vue';
|
|
6
6
|
|
|
7
7
|
export default Vue.extend({
|
|
8
|
-
props: ['itemId', 'imageMetadata', 'frameUpdate'],
|
|
8
|
+
props: ['itemId', 'imageMetadata', 'frameUpdate', 'liConfig'],
|
|
9
9
|
components: { CompositeLayers, DualInput, PresetsMenu },
|
|
10
10
|
data() {
|
|
11
11
|
return {
|
|
@@ -75,7 +75,8 @@ export default Vue.extend({
|
|
|
75
75
|
}
|
|
76
76
|
});
|
|
77
77
|
this.currentFrame = frame
|
|
78
|
-
let style = this.currentModeId > 1 ? this.style[this.currentModeId] : undefined
|
|
78
|
+
let style = this.currentModeId > 1 ? Object.assign({}, this.style[this.currentModeId]) : undefined
|
|
79
|
+
if(style && style.preset) delete style.preset
|
|
79
80
|
this.frameUpdate(frame, style);
|
|
80
81
|
},
|
|
81
82
|
fillMetadata() {
|
|
@@ -200,6 +201,9 @@ export default Vue.extend({
|
|
|
200
201
|
</select>
|
|
201
202
|
<presets-menu
|
|
202
203
|
:itemId="itemId"
|
|
204
|
+
:liConfig="liConfig"
|
|
205
|
+
:imageMetadata="imageMetadata"
|
|
206
|
+
:availableModes="sliderModes.map((m) => m.id)"
|
|
203
207
|
:currentMode="sliderModes.find((m) => m.id === currentModeId)"
|
|
204
208
|
:currentFrame="currentFrame"
|
|
205
209
|
:currentStyle="style[currentModeId]"
|
|
@@ -2,11 +2,12 @@
|
|
|
2
2
|
import { restRequest } from '@girder/core/rest';
|
|
3
3
|
|
|
4
4
|
export default {
|
|
5
|
-
props: ['itemId', 'currentMode', 'currentFrame', 'currentStyle'],
|
|
5
|
+
props: ['itemId', 'liConfig', 'imageMetadata', 'availableModes', 'currentMode', 'currentFrame', 'currentStyle'],
|
|
6
6
|
emits: ['setCurrentMode', 'setCurrentFrame', 'updateStyle'],
|
|
7
7
|
data() {
|
|
8
8
|
return {
|
|
9
|
-
|
|
9
|
+
itemPresets: [],
|
|
10
|
+
folderPresets: [],
|
|
10
11
|
selectedPreset: undefined,
|
|
11
12
|
showPresetCreation: false,
|
|
12
13
|
newPresetName: undefined,
|
|
@@ -14,13 +15,36 @@ export default {
|
|
|
14
15
|
}
|
|
15
16
|
},
|
|
16
17
|
methods: {
|
|
18
|
+
presetApplicable(preset) {
|
|
19
|
+
if (this.itemPresets.find((p) => p.name === preset.name)) {
|
|
20
|
+
// preset with this name already exists on the item,
|
|
21
|
+
// prefer the item preset; don't show both
|
|
22
|
+
return false
|
|
23
|
+
} else if (
|
|
24
|
+
parseInt(preset.frame) >= this.imageMetadata.frames.length
|
|
25
|
+
|| !this.availableModes.includes(preset.mode.id)
|
|
26
|
+
) {
|
|
27
|
+
return false
|
|
28
|
+
} else if (
|
|
29
|
+
preset.style && preset.style.bands
|
|
30
|
+
&& this.imageMetadata.IndexRange.IndexC
|
|
31
|
+
&& preset.style.bands.some((b) => b.framedelta > this.imageMetadata.IndexRange.IndexC)
|
|
32
|
+
) {
|
|
33
|
+
return false
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return true
|
|
37
|
+
},
|
|
17
38
|
getPresets() {
|
|
18
39
|
restRequest({
|
|
19
40
|
type: 'GET',
|
|
20
41
|
url: 'item/' + this.itemId + '/internal_metadata/presets',
|
|
21
42
|
}).then((presets) => {
|
|
22
43
|
if (presets) {
|
|
23
|
-
this.
|
|
44
|
+
this.itemPresets = presets
|
|
45
|
+
}
|
|
46
|
+
if (this.liConfig.imageFramePresets) {
|
|
47
|
+
this.folderPresets = this.liConfig.imageFramePresets.filter(this.presetApplicable)
|
|
24
48
|
}
|
|
25
49
|
})
|
|
26
50
|
},
|
|
@@ -35,8 +59,8 @@ export default {
|
|
|
35
59
|
if (!overwrite && this.availablePresets.find((p) => p.name === newPreset.name)) {
|
|
36
60
|
this.errorMessage = `There is already a preset named "${newPreset.name}". Overwrite "${newPreset.name}"?`
|
|
37
61
|
} else {
|
|
38
|
-
this.
|
|
39
|
-
this.
|
|
62
|
+
this.itemPresets = this.itemPresets.filter((p) => p.name !== newPreset.name)
|
|
63
|
+
this.itemPresets.push(newPreset)
|
|
40
64
|
this.selectedPreset = newPreset.name
|
|
41
65
|
this.savePresetsList()
|
|
42
66
|
this.newPresetName = undefined
|
|
@@ -45,7 +69,7 @@ export default {
|
|
|
45
69
|
}
|
|
46
70
|
},
|
|
47
71
|
deleteSelectedPreset() {
|
|
48
|
-
this.
|
|
72
|
+
this.itemPresets = this.itemPresets.filter((p) => p.name !== this.selectedPreset)
|
|
49
73
|
this.selectedPreset = undefined
|
|
50
74
|
this.savePresetsList()
|
|
51
75
|
},
|
|
@@ -53,47 +77,48 @@ export default {
|
|
|
53
77
|
restRequest({
|
|
54
78
|
type: 'PUT',
|
|
55
79
|
url: 'item/' + this.itemId + '/internal_metadata/presets',
|
|
56
|
-
data: JSON.stringify(this.
|
|
80
|
+
data: JSON.stringify(this.itemPresets),
|
|
57
81
|
contentType: 'application/json',
|
|
58
82
|
})
|
|
59
83
|
},
|
|
84
|
+
styleFromAutoRange(band) {
|
|
85
|
+
band = Object.assign({}, band) // new reference
|
|
86
|
+
if (band.autoRange) {
|
|
87
|
+
band.min = `min:${band.autoRange / 100}`
|
|
88
|
+
band.max = `max:${band.autoRange / 100}`
|
|
89
|
+
delete band.autoRange
|
|
90
|
+
}
|
|
91
|
+
return band
|
|
92
|
+
},
|
|
60
93
|
styleEqual(style1, style2) {
|
|
61
94
|
if (style1 === style2) {
|
|
62
95
|
return true
|
|
63
96
|
}
|
|
64
|
-
if (style1.
|
|
97
|
+
if (style1.length !== style2.length) {
|
|
65
98
|
return false
|
|
66
99
|
}
|
|
67
|
-
return style1.
|
|
68
|
-
b1 =
|
|
69
|
-
|
|
70
|
-
|
|
100
|
+
return style1.every((b1) => {
|
|
101
|
+
b1 = this.styleFromAutoRange(b1)
|
|
102
|
+
let b2 = style2.find((b) => b.framedelta === b1.framedelta && b.band === b1.band)
|
|
103
|
+
if (b2) {
|
|
104
|
+
b2 = this.styleFromAutoRange(b2)
|
|
71
105
|
return (
|
|
72
|
-
|
|
73
|
-
&&
|
|
106
|
+
b1.min === b2.min
|
|
107
|
+
&& b1.max === b2.max
|
|
108
|
+
&& b1.palette === b2.palette
|
|
74
109
|
)
|
|
75
|
-
}
|
|
110
|
+
} else return false
|
|
76
111
|
})
|
|
77
112
|
},
|
|
78
113
|
checkPresetMatch() {
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
}
|
|
88
|
-
return b
|
|
89
|
-
})
|
|
90
|
-
} : this.currentStyle
|
|
91
|
-
const match = this.availablePresets.find((p) => (
|
|
92
|
-
p.mode.id === this.currentMode.id
|
|
93
|
-
&& p.frame === this.currentFrame
|
|
94
|
-
&& this.styleEqual(targetStyle, p.style)
|
|
95
|
-
))
|
|
96
|
-
this.selectedPreset = match ? match.name : undefined
|
|
114
|
+
if (this.currentStyle) {
|
|
115
|
+
const match = this.availablePresets.find((p) => (
|
|
116
|
+
p.mode.id === this.currentMode.id
|
|
117
|
+
&& p.frame === this.currentFrame
|
|
118
|
+
&& this.styleEqual(this.currentStyle.bands, p.style.bands)
|
|
119
|
+
))
|
|
120
|
+
this.selectedPreset = match ? match.name : undefined
|
|
121
|
+
}
|
|
97
122
|
}
|
|
98
123
|
},
|
|
99
124
|
computed: {
|
|
@@ -105,6 +130,9 @@ export default {
|
|
|
105
130
|
name = `${this.currentStyle.bands.length} bands`
|
|
106
131
|
}
|
|
107
132
|
return name;
|
|
133
|
+
},
|
|
134
|
+
availablePresets() {
|
|
135
|
+
return this.itemPresets.concat(this.folderPresets)
|
|
108
136
|
}
|
|
109
137
|
},
|
|
110
138
|
watch: {
|
|
@@ -122,8 +150,21 @@ export default {
|
|
|
122
150
|
if (preset.frame !== undefined) {
|
|
123
151
|
this.$emit('setCurrentFrame', preset.frame)
|
|
124
152
|
}
|
|
125
|
-
if (preset.style &&
|
|
126
|
-
|
|
153
|
+
if (preset.style && preset.style.bands.length) {
|
|
154
|
+
const styleArray = []
|
|
155
|
+
preset.style.bands.forEach((layer) => {
|
|
156
|
+
const styleEntry = {
|
|
157
|
+
min: layer.autoRange !== undefined ? `min:${layer.autoRange / 100}` : parseInt(layer.min),
|
|
158
|
+
max: layer.autoRange !== undefined ? `max:${layer.autoRange / 100}` : parseInt(layer.max),
|
|
159
|
+
palette: layer.palette,
|
|
160
|
+
framedelta: layer.framedelta,
|
|
161
|
+
band: layer.band,
|
|
162
|
+
}
|
|
163
|
+
if (!styleEntry.min) delete styleEntry.min
|
|
164
|
+
if (!styleEntry.max) delete styleEntry.max
|
|
165
|
+
styleArray.push(styleEntry);
|
|
166
|
+
});
|
|
167
|
+
this.$emit('updateStyle', preset.mode.id, {bands: styleArray, preset: true})
|
|
127
168
|
}
|
|
128
169
|
}
|
|
129
170
|
},
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
girder>=3.1.18
|
|
2
2
|
girder-jobs>=3.0.3
|
|
3
|
-
large_image>=1.23.3.
|
|
3
|
+
large_image>=1.23.3.dev59
|
|
4
4
|
|
|
5
5
|
[:python_version < "3.8"]
|
|
6
6
|
importlib-metadata<5
|
|
7
7
|
|
|
8
8
|
[tasks]
|
|
9
|
-
large-image-tasks[girder]>=1.23.3.
|
|
9
|
+
large-image-tasks[girder]>=1.23.3.dev59
|
|
10
10
|
girder-worker[girder]>=0.6.0
|
{girder-large-image-1.23.3.dev31 → girder-large-image-1.23.3.dev59}/test_girder/test_tiles_rest.py
RENAMED
|
@@ -1499,3 +1499,30 @@ def testThumbnailMaintenance(server, admin, fsAssetstore):
|
|
|
1499
1499
|
resp = server.request(path='/item/%s/tiles/thumbnails' % itemId, user=admin)
|
|
1500
1500
|
assert utilities.respStatus(resp) == 200
|
|
1501
1501
|
assert len(resp.json) == 0
|
|
1502
|
+
|
|
1503
|
+
# Get a thumbnail
|
|
1504
|
+
resp = server.request(path='/item/%s/tiles/thumbnail' % itemId,
|
|
1505
|
+
user=admin, isJson=False)
|
|
1506
|
+
assert utilities.respStatus(resp) == 200
|
|
1507
|
+
thumb = utilities.getBody(resp, text=False)
|
|
1508
|
+
resp = server.request(path='/item/%s/tiles/thumbnails' % itemId, user=admin)
|
|
1509
|
+
assert utilities.respStatus(resp) == 200
|
|
1510
|
+
# Ask to delete it specifically
|
|
1511
|
+
key = resp.json[0]['thumbnailKey']
|
|
1512
|
+
resp = server.request(
|
|
1513
|
+
path='/item/%s/tiles/thumbnails' % itemId, method='DELETE', user=admin,
|
|
1514
|
+
params={'key': key})
|
|
1515
|
+
assert utilities.respStatus(resp) == 200
|
|
1516
|
+
assert len(resp.json) == 1
|
|
1517
|
+
# It should be gone
|
|
1518
|
+
resp = server.request(path='/item/%s/tiles/thumbnails' % itemId, user=admin)
|
|
1519
|
+
assert utilities.respStatus(resp) == 200
|
|
1520
|
+
assert len(resp.json) == 0
|
|
1521
|
+
# Add it back
|
|
1522
|
+
resp = server.request(
|
|
1523
|
+
path='/item/%s/tiles/thumbnails' % itemId, method='POST', user=admin,
|
|
1524
|
+
params={'key': key}, body=thumb, type='application/octet-stream')
|
|
1525
|
+
|
|
1526
|
+
resp = server.request(path='/item/%s/tiles/thumbnails' % itemId, user=admin)
|
|
1527
|
+
assert utilities.respStatus(resp) == 200
|
|
1528
|
+
assert len(resp.json) == 1
|
|
File without changes
|
|
File without changes
|
{girder-large-image-1.23.3.dev31 → girder-large-image-1.23.3.dev59}/girder_large_image/__init__.py
RENAMED
|
File without changes
|
{girder-large-image-1.23.3.dev31 → girder-large-image-1.23.3.dev59}/girder_large_image/constants.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{girder-large-image-1.23.3.dev31 → girder-large-image-1.23.3.dev59}/test_girder/girder_utilities.py
RENAMED
|
File without changes
|
{girder-large-image-1.23.3.dev31 → girder-large-image-1.23.3.dev59}/test_girder/test_large_image.py
RENAMED
|
File without changes
|
{girder-large-image-1.23.3.dev31 → girder-large-image-1.23.3.dev59}/test_girder/test_web_client.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|