Closed stephandooper closed 3 days ago
Hi @stephandooper,
Have you tried with openslide 4? I think this fails with the old openslide 3.4.1, but openslide4 ought to fix it, I think. It seems to work for me:
$ vipsheader -f xres CMU-1.svs
2004.0080160320642
$ vips crop CMU-1.svs x.tif[tile,compression=jpeg,pyramid] 0 0 1000 1000
$ vipsheader -f xres x.tif
2004.008056640625
So openslideload from a SVS works OK. If I read the same TIFF back again I see:
$ vips openslideload x.tif x.v
$ vipsheader -f xres x.v
2004.008031496063
So it has the res back from the openslide vanilla TIFF reader too.
(openslide4 still isn't in current ubuntu, but I think it'll be in 24.10)
Good call, I'm indeed using 3.4.1. I'll try openslide 4 and get back to you
I just updated to 24.10 and openslide is still 3.4.1 sigh.
It ought to be simple to build from source at least.
I managed to build openslide 4.0 without any hassle. Unfortunately the vipsheader command still returns an xres of 1, would have any idea why?
This is my build information:
openslide: openslide-show-properties --version openslide-show-properties 4.0.0, using OpenSlide 4.0.0
pyvips: enable debug: false enable deprecated: true enable modules: true enable cplusplus: true enable RAD load/save: true enable Analyze7 load: true enable PPM load/save: true enable GIF load: true FFTs with fftw3: true SIMD support with orc-0.4: true ICC profile support with lcms2: true deflate compression with zlib: true text rendering with pangocairo: true font file support with fontconfig: true EXIF metadata support with libexif: true JPEG load/save with libjpeg: true JXL load/save with libjxl: false (dynamic module: false) JPEG2000 load/save with libopenjp2: true PNG load/save with libpng: true image quantisation with imagequant: true TIFF load/save with libtiff-4: true image pyramid save with libarchive: true HEIC/AVIF load/save with libheif: false (dynamic module: false) WebP load/save with libwebp: true PDF load with poppler-glib: true (dynamic module: true) SVG load with librsvg-2.0: true EXR load with OpenEXR: true WSI load with openslide: true (dynamic module: true) Matlab load with matio: true NIfTI load/save with libnifti: false FITS load/save with cfitsio: true GIF save with cgif: false Magick load/save with MagickCore: false (dynamic module: false)
What do you see for meson output during configure? I have:
vips 8.17.0
Dependencies
glib-2.0 : 2.82.1
gio-2.0 : 2.82.1
gobject-2.0 : 2.82.1
gmodule-no-export-2.0 : 2.82.1
expat : 2.6.2
zlib : 1.3.1
libarchive : 3.7.4
fftw3 : 3.3.10
cfitsio : 4.4.1
imagequant : 2.18.0
cgif : 0.4.1
libexif : 0.6.24
libjpeg : 2.1.5
spng : 0.7.4
libwebp : 1.4.0
libwebpmux : 1.4.0
libwebpdemux : 1.4.0
pangocairo : 1.54.0
pangoft2 : 1.54.0
fontconfig : 2.15.0
libtiff-4 : 4.5.1
librsvg-2.0 : 2.59.1
cairo : 1.18.2
matio : 1.5.27
lcms2 : 2.14
OpenEXR : 3.1.5
libopenjp2 : 2.5.0
libhwy : 1.2.0
niftiio : 3.0.1
MagickCore : 6.9.13
openslide : 4.0.0
libheif : 1.18.1
libjxl : 0.10.3
libjxl_threads : 0.10.3
poppler-glib : 24.08.0
Could pyvips be picking up an old libvips?
I made a tiny test program so we can be sure we're testing the same thing:
#!/usr/bin/env python3
import sys
import pyvips
image = pyvips.Image.new_from_file(sys.argv[1])
# take a small part of the image, to keep speed reasonable
image = image.crop(0, 0, min(1000, image.width), min(1000, image.height))
print(f"original image xres = {image.xres}")
# have to save to a file so openslide can load it
image.tiffsave("x.tif", compression="jpeg", tile=True, pyramid=True)
tiffload = pyvips.Image.tiffload("x.tif")
print(f"after tiffsave/tiffload, xres = {tiffload.xres}")
openslideload = pyvips.Image.openslideload("x.tif")
print(f"after tiffsave/openslideload, xres = {openslideload.xres}")
I see:
$ ./openslide-res.py ~/pics/openslide/CMU-1.svs
original image xres = 2004.0080160320642
after tiffsave/tiffload, xres = 2004.008056640625
after tiffsave/openslideload, xres = 2004.0080585629923
Okay I managed to fix it. The conclusion was that I made a rookie mistake.
I messed up the order and first compiled libvips, and then compiled openslide, so vips was still using openslide 3.4.1
After compiling in the correct order I tested everything again and openslideload now gives the correct xres and yres:
$ vipsheader -f xres normal_001.tif
4113.6349606299209$ vips crop xres normal_001.tif x.tif[tile,compression=jpeg,pyramid] 0 0 1000 1000
$ vipsheader -f xres x.tif
4113.6349606299209
Verifiying that openslide indeed loads the correct resolution:
$ vips openslideload x.tif x.v
$ vipsheader -f xres x.v
4113.6349606299209```
So everything works now. Thanks!
Great!
Did you get libdicom too? openslide4 now has reasonable DICOM slide support, which can be handy. It also supports slide colour management.
vipsdisp can be useful for viewing slides:
https://flathub.org/en-GB/apps/org.libvips.vipsdisp
https://github.com/jcupitt/vipsdisp
The README has some notes on the keybindings.
No, I didn't know about this, I'll check it out right away. Thanks for the heads up!
(if you use the flatpak build of vipsdisp, it has openslide4, libdicom, and slide colour management support built in)
Hi,
I was playing around with the pyvips image loaders new_from_file and openslideload. I noticed that when you write an image using pyvips and then load it using openslideload, then openslideload will always set the xres/yres metadata to 1. This happens even if it's forced during writing.
Pyvips version: 2.2.3 libvips version: 8.16 (also tested on 8.12)
image data used: I'm using normal_001.tif from the CAMELYON16 dataset: https://camelyon17.grand-challenge.org/Data/ I also found this same problem using several svs files from TCGA so it might be a wider thing