large-image-source-vips 1.30.7.dev71__tar.gz → 1.31.1.dev2__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.
- {large_image_source_vips-1.30.7.dev71 → large_image_source_vips-1.31.1.dev2}/PKG-INFO +2 -2
- {large_image_source_vips-1.30.7.dev71 → large_image_source_vips-1.31.1.dev2}/large_image_source_vips/__init__.py +73 -10
- {large_image_source_vips-1.30.7.dev71 → large_image_source_vips-1.31.1.dev2}/large_image_source_vips.egg-info/PKG-INFO +2 -2
- {large_image_source_vips-1.30.7.dev71 → large_image_source_vips-1.31.1.dev2}/large_image_source_vips.egg-info/requires.txt +1 -1
- {large_image_source_vips-1.30.7.dev71 → large_image_source_vips-1.31.1.dev2}/LICENSE +0 -0
- {large_image_source_vips-1.30.7.dev71 → large_image_source_vips-1.31.1.dev2}/README.rst +0 -0
- {large_image_source_vips-1.30.7.dev71 → large_image_source_vips-1.31.1.dev2}/large_image_source_vips/girder_source.py +0 -0
- {large_image_source_vips-1.30.7.dev71 → large_image_source_vips-1.31.1.dev2}/large_image_source_vips.egg-info/SOURCES.txt +0 -0
- {large_image_source_vips-1.30.7.dev71 → large_image_source_vips-1.31.1.dev2}/large_image_source_vips.egg-info/dependency_links.txt +0 -0
- {large_image_source_vips-1.30.7.dev71 → large_image_source_vips-1.31.1.dev2}/large_image_source_vips.egg-info/entry_points.txt +0 -0
- {large_image_source_vips-1.30.7.dev71 → large_image_source_vips-1.31.1.dev2}/large_image_source_vips.egg-info/top_level.txt +0 -0
- {large_image_source_vips-1.30.7.dev71 → large_image_source_vips-1.31.1.dev2}/pyproject.toml +0 -0
- {large_image_source_vips-1.30.7.dev71 → large_image_source_vips-1.31.1.dev2}/setup.cfg +0 -0
- {large_image_source_vips-1.30.7.dev71 → large_image_source_vips-1.31.1.dev2}/setup.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: large-image-source-vips
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.31.1.dev2
|
|
4
4
|
Summary: A libvips tilesource for large_image.
|
|
5
5
|
Home-page: https://github.com/girder/large_image
|
|
6
6
|
Author: Kitware, Inc.
|
|
@@ -19,7 +19,7 @@ Classifier: Programming Language :: Python :: 3.13
|
|
|
19
19
|
Requires-Python: >=3.8
|
|
20
20
|
Description-Content-Type: text/x-rst
|
|
21
21
|
License-File: LICENSE
|
|
22
|
-
Requires-Dist: large-image>=1.
|
|
22
|
+
Requires-Dist: large-image>=1.31.1.dev2
|
|
23
23
|
Requires-Dist: numpy
|
|
24
24
|
Requires-Dist: packaging
|
|
25
25
|
Requires-Dist: pyvips
|
|
@@ -16,7 +16,7 @@ from large_image.constants import (NEW_IMAGE_PATH_FLAG, TILE_FORMAT_NUMPY,
|
|
|
16
16
|
dtypeToGValue)
|
|
17
17
|
from large_image.exceptions import TileSourceError, TileSourceFileNotFoundError
|
|
18
18
|
from large_image.tilesource import FileTileSource
|
|
19
|
-
from large_image.tilesource.utilities import _imageToNumpy, _newFromFileLock
|
|
19
|
+
from large_image.tilesource.utilities import _imageToNumpy, _newFromFileLock, nearPowerOfTwo
|
|
20
20
|
|
|
21
21
|
logging.getLogger('pyvips').setLevel(logging.ERROR)
|
|
22
22
|
|
|
@@ -98,6 +98,7 @@ class VipsFileTileSource(FileTileSource, metaclass=LruCacheMetaclass):
|
|
|
98
98
|
if 'n-pages' in self._image.get_fields():
|
|
99
99
|
pages = self._image.get('n-pages')
|
|
100
100
|
self._frames = [0]
|
|
101
|
+
self._lowres = {}
|
|
101
102
|
for page in range(1, pages):
|
|
102
103
|
subInputPath = self._largeImagePath + f'[page={page}{self._suffix}]'
|
|
103
104
|
with _newFromFileLock:
|
|
@@ -113,8 +114,13 @@ class VipsFileTileSource(FileTileSource, metaclass=LruCacheMetaclass):
|
|
|
113
114
|
self._frames.append(page)
|
|
114
115
|
continue
|
|
115
116
|
if subImage.width * subImage.height < self.sizeX * self.sizeY:
|
|
117
|
+
if (nearPowerOfTwo(self.sizeX, subImage.width) and
|
|
118
|
+
nearPowerOfTwo(self.sizeY, subImage.height)):
|
|
119
|
+
level = int(round(math.log(self.sizeX / subImage.width) / math.log(2)))
|
|
120
|
+
self._lowres.setdefault(len(self._frames) - 1, {})[level] = page
|
|
116
121
|
continue
|
|
117
122
|
self._frames = [page]
|
|
123
|
+
self._lowres = {}
|
|
118
124
|
self.sizeX = subImage.width
|
|
119
125
|
self.sizeY = subImage.height
|
|
120
126
|
try:
|
|
@@ -122,12 +128,41 @@ class VipsFileTileSource(FileTileSource, metaclass=LruCacheMetaclass):
|
|
|
122
128
|
except Exception:
|
|
123
129
|
pass
|
|
124
130
|
self._image = subImage
|
|
131
|
+
self._checkLowerLevels()
|
|
125
132
|
self.levels = int(max(1, math.ceil(math.log(
|
|
126
133
|
float(max(self.sizeX, self.sizeY)) / self.tileWidth) / math.log(2)) + 1))
|
|
127
|
-
if len(self._frames) > 1:
|
|
134
|
+
if len(self._frames) > 1 or self._lowres is not None:
|
|
128
135
|
self._recentFrames = cachetools.LRUCache(maxsize=6)
|
|
129
136
|
self._frameLock = threading.RLock()
|
|
130
137
|
|
|
138
|
+
def _checkLowerLevels(self):
|
|
139
|
+
if (len(self._lowres) != len(self._frames) or
|
|
140
|
+
min(len(v) for v in self._lowres.values()) !=
|
|
141
|
+
max(len(v) for v in self._lowres.values()) or
|
|
142
|
+
min(len(v) for v in self._lowres.values()) == 0):
|
|
143
|
+
self._lowres = None
|
|
144
|
+
if len(self._frames) == 1 and 'openslide.level-count' in self._image.get_fields():
|
|
145
|
+
self._lowres = [{}]
|
|
146
|
+
for oslevel in range(1, int(self._image.get('openslide.level-count'))):
|
|
147
|
+
with _newFromFileLock:
|
|
148
|
+
try:
|
|
149
|
+
subImage = pyvips.Image.new_from_file(
|
|
150
|
+
self._largeImagePath, level=oslevel)
|
|
151
|
+
except Exception:
|
|
152
|
+
continue
|
|
153
|
+
if subImage.width * subImage.height < self.sizeX * self.sizeY:
|
|
154
|
+
if (nearPowerOfTwo(self.sizeX, subImage.width) and
|
|
155
|
+
nearPowerOfTwo(self.sizeY, subImage.height)):
|
|
156
|
+
level = int(round(math.log(
|
|
157
|
+
self.sizeX / subImage.width) / math.log(2)))
|
|
158
|
+
self._lowres[0][level] = (self._frames[0], oslevel)
|
|
159
|
+
if not len(self._lowres[0]):
|
|
160
|
+
self._lowres = None
|
|
161
|
+
else:
|
|
162
|
+
self._lowres = list(self._lowres.values())
|
|
163
|
+
if self._lowres is not None:
|
|
164
|
+
self._populatedLevels = len(self._lowres[0]) + 1
|
|
165
|
+
|
|
131
166
|
def _initNew(self, **kwargs):
|
|
132
167
|
"""
|
|
133
168
|
Initialize the tile class for creating a new image.
|
|
@@ -139,6 +174,7 @@ class VipsFileTileSource(FileTileSource, metaclass=LruCacheMetaclass):
|
|
|
139
174
|
self.sizeX = self.sizeY = self.levels = 0
|
|
140
175
|
self.tileWidth = self.tileHeight = self._tileSize
|
|
141
176
|
self._frames = [0]
|
|
177
|
+
self._lowres = None
|
|
142
178
|
self._cacheValue = str(uuid.uuid4())
|
|
143
179
|
self._output = None
|
|
144
180
|
self._editable = True
|
|
@@ -194,25 +230,38 @@ class VipsFileTileSource(FileTileSource, metaclass=LruCacheMetaclass):
|
|
|
194
230
|
self._addMetadataFrameInformation(result)
|
|
195
231
|
return result
|
|
196
232
|
|
|
197
|
-
def _getFrameImage(self, frame=0):
|
|
233
|
+
def _getFrameImage(self, frame=0, lowres=None):
|
|
198
234
|
"""
|
|
199
235
|
Get the vips image associated with a specific frame.
|
|
200
236
|
|
|
201
237
|
:param frame: the 0-based frame to get.
|
|
238
|
+
:param lowres: the lower resolution part of the frame
|
|
202
239
|
:returns: a vips image.
|
|
203
240
|
"""
|
|
204
241
|
if self._image is None and self._output:
|
|
205
242
|
self._outputToImage()
|
|
206
243
|
img = self._image
|
|
207
|
-
if frame > 0:
|
|
244
|
+
if frame > 0 or lowres:
|
|
208
245
|
with self._frameLock:
|
|
209
|
-
|
|
210
|
-
|
|
246
|
+
key = (frame, lowres)
|
|
247
|
+
frameval = self._frames[frame]
|
|
248
|
+
params = {}
|
|
249
|
+
if lowres is not None:
|
|
250
|
+
if isinstance(self._lowres[frame][lowres], tuple):
|
|
251
|
+
frameval = self._lowres[frame][lowres][0]
|
|
252
|
+
params = {'level': self._lowres[frame][lowres][1]}
|
|
253
|
+
else:
|
|
254
|
+
frameval = self._lowres[frame][lowres]
|
|
255
|
+
if key not in self._recentFrames:
|
|
256
|
+
if frameval:
|
|
257
|
+
subpath = self._largeImagePath + f'[page={frameval}{self._suffix}]'
|
|
258
|
+
else:
|
|
259
|
+
subpath = self._largeImagePath
|
|
211
260
|
with _newFromFileLock:
|
|
212
|
-
img = pyvips.Image.new_from_file(subpath)
|
|
213
|
-
self._recentFrames[
|
|
261
|
+
img = pyvips.Image.new_from_file(subpath, **params)
|
|
262
|
+
self._recentFrames[key] = img
|
|
214
263
|
else:
|
|
215
|
-
img = self._recentFrames[
|
|
264
|
+
img = self._recentFrames[key]
|
|
216
265
|
return img
|
|
217
266
|
|
|
218
267
|
def getNativeMagnification(self):
|
|
@@ -231,8 +280,22 @@ class VipsFileTileSource(FileTileSource, metaclass=LruCacheMetaclass):
|
|
|
231
280
|
def getTile(self, x, y, z, pilImageAllowed=False, numpyAllowed=False, **kwargs):
|
|
232
281
|
frame = self._getFrame(**kwargs)
|
|
233
282
|
self._xyzInRange(x, y, z, frame, len(self._frames))
|
|
234
|
-
img = self._getFrameImage(frame)
|
|
235
283
|
x0, y0, x1, y1, step = self._xyzToCorners(x, y, z)
|
|
284
|
+
lowres = None
|
|
285
|
+
if self._lowres and step > 1:
|
|
286
|
+
use = 0
|
|
287
|
+
for ll in self._lowres[frame].keys():
|
|
288
|
+
if 2 ** ll <= step:
|
|
289
|
+
use = max(use, ll)
|
|
290
|
+
if use:
|
|
291
|
+
lowres = use
|
|
292
|
+
div = 2 ** use
|
|
293
|
+
x0 //= div
|
|
294
|
+
y0 //= div
|
|
295
|
+
x1 //= div
|
|
296
|
+
y1 //= div
|
|
297
|
+
step //= div
|
|
298
|
+
img = self._getFrameImage(frame, lowres)
|
|
236
299
|
tileimg = img.crop(min(x0, img.width), min(y0, img.height),
|
|
237
300
|
min(x1, img.width) - min(x0, img.width),
|
|
238
301
|
min(y1, img.height) - min(y0, img.height))
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: large-image-source-vips
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.31.1.dev2
|
|
4
4
|
Summary: A libvips tilesource for large_image.
|
|
5
5
|
Home-page: https://github.com/girder/large_image
|
|
6
6
|
Author: Kitware, Inc.
|
|
@@ -19,7 +19,7 @@ Classifier: Programming Language :: Python :: 3.13
|
|
|
19
19
|
Requires-Python: >=3.8
|
|
20
20
|
Description-Content-Type: text/x-rst
|
|
21
21
|
License-File: LICENSE
|
|
22
|
-
Requires-Dist: large-image>=1.
|
|
22
|
+
Requires-Dist: large-image>=1.31.1.dev2
|
|
23
23
|
Requires-Dist: numpy
|
|
24
24
|
Requires-Dist: packaging
|
|
25
25
|
Requires-Dist: pyvips
|
|
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
|