0

I am trying to extract a whole scale image from a SVS file in C++.

I saw an explanation from the OpenSlide homepage. It says the SVS format is "single-file pyramidal tiled TIFF".

So I tried to extract a whole-scale image like I did for TIFF image: I read all IFDs from the SVS file, but there is no 273 tag which contains an address pointing to a whole scale image.

That's why I am little confused now, the SVS format doesn't have a whole scale image inside the file?

I found an undefined private tag from a SVS file which number is 34675. Is this tag is for a whole scale image? Or is there a proper way to extract it?

Cris Luengo
  • 55,762
  • 10
  • 62
  • 120
YJJ
  • 45
  • 10

2 Answers2

1

Aperio SVS is a tiled format. All levels of the pyramid are tiled images. The base layer is the first TIFF directory. This page of the LibTiff documentation shows how to read tiled images.

In short, you need to look for tag 324 (TIFFTAG_TILEOFFSETS), as well as tags 322 and 323 (TIFFTAG_TILEWIDTH, TIFFTAG_TILELENGTH). I highly recommend you use LibTiff for this, and don’t try to roll your own.

The custom tag in the SVS file contains metadata, including the physical size of a pixel in micron (SVS doesn’t set the resolution TIFF tags).

Cris Luengo
  • 55,762
  • 10
  • 62
  • 120
  • I see. Thanks for replying @Cris Luengo. So, there is no way to extract an whole image at once, Am I right ? I have to extract all tiles anyway and connect the tiles making the whole image. I thought that the first page of all tiff files is an whole scale image. but that is not the case for svs file format. am I understand correctly ? Thanks a lot ahead. P.S> And I also want you to let me know what is tag "34675". a description says it is "TIFF Tag ICC Profile". I don't understand what that means. – YJJ Nov 18 '18 at 06:04
  • @YJJ: You cannot extract it in a single function call, but that is true for striped TIFF files also (there you have to read each strip in, and compose them into an image). With the tiled TIFF, you read in each tile, and compose them into an image. The first page of the SVS file is the full-scale image (base layer), as you expected. But each page of any TIFF file is composed of either one or more strips, or one or more tiles. TIFF just likes to break up the pixel data in that way. – Cris Luengo Nov 18 '18 at 06:45
  • @YJJ: ICC profiles describe how you should modify the colors in the file so that they look the same on your monitor as they do on the physical slide. For that, you need to combine the ICC profile of the scanner (stored in the SVS file) with the ICC profile of the monitor. See here: https://en.wikipedia.org/wiki/ICC_profile -- But it is best to ignore the ICC profile if you are doing analysis of the slide. It is only useful for display. – Cris Luengo Nov 18 '18 at 06:47
  • Thank you so much for your answer. So, on the first page, there is full-scale image but not with a single array. the full-scale image is divided into tiles or strips. I wonder, all svs files have tiles to compose the full-scale image not strips? now I am coding for extracting JPEG2000 formatted file from a svs file and convert JPEG2000 to the normal JPEG. So, Now I don't need to consider about strips on svs file, just use tile information to compose the full-scale image? – YJJ Nov 18 '18 at 07:35
  • If you don't mind, I also want to ask you that after I extreact full-scale image composing all tiles, it would be buffer array. is there any right way to save the buffer array into JP2 file format ? – YJJ Nov 18 '18 at 07:38
  • @YJJ: Yes, all TIFF files divide the image up into strips **or** tiles, not both (though for small images maybe it's just one strip or one tile). Yes, all SVS files use tiles for all layers in the pyramid. The macro image and the label image use strips (these are in the directories at the end of the SVS file, you probably want to ignore them). Sorry, I don't know anything about the JP2 file format. – Cris Luengo Nov 18 '18 at 07:50
  • I tried to use libtiff and got this error: "Compression scheme 33005 tile decoding is not implemented". I think that's because a svs format using JPEG2000 as their compression method. What I really want to do is that just save a full-scale image with any format types. It seems like the up-to-date libtiff still doesn't handle JPEG2000 format. that means I have to make my own solution. which type should I use for composing all tile images? after composing the image, I think I will just save the buffer array with ofstream. – YJJ Nov 18 '18 at 14:09
  • @YJJ: JPEG2000 is a custom addition to the TIFF standard, very few TIFF readers support it. I think it is possible to configure LibTiff to use it (when compiling the library), but you don’t need to: Use `TIFFReadRawTile` to read the tile data, then decompress using your jpeg2k decompression library. Then write the tile data into your larger image. – Cris Luengo Nov 18 '18 at 14:55
  • Hi, @Cris Luengo. Since I have never used libtiff, there are some issues I have now. After I read a svs file I want to use and setFiels like image_width, image_length, tile_width, tile_length, sample_per_pixel, bits_per_sample. I did, for (int tile = 0; tile < TIFFNumberOfTiles(tiff_in); tile++){ TIFFReadRawTile(tiff_in, tile, buf, (tsize_t)-1); TIFFWriteRawTile(tiff_out, tile, buf, (tsize_t)sizeof(buf)); } But after this, I got only 43KB output raw file from 152MB svs file. there must be some mistakes. should I write the tiles after completing reading all of them first? Thanks – YJJ Nov 21 '18 at 10:40
  • @YJJ: You need to set up the output TIFF directory first: set image sizes, set it to tiled mode, set tile sizes, set compression, set photometric interpretation, etc. After that you can write tiles. I’m guessing this is what is wrong, but I can’t be sure with the small snippet you shared. Why don’t you make a new question for this? – Cris Luengo Nov 21 '18 at 14:00
  • Thank you @Cris Luengo. I confirmed that X resolution and Y resolution tags are not set in svs files I have. Is there other ways to get dpi information without using TIFFGetField ? – YJJ Jan 21 '19 at 10:12
  • @YJJ: SVS files have a custom tag in the first directory that contains a block of metadata in XML format. You can get DPI info from there. Read the custom tag, parse the XML, get the value in the appropriate field. If you dump the data, you’ll quickly find out which tag it is and which XML field to look for. Use command line utilities `tiffinfo` and `tuffdump` to examine the tiff file. – Cris Luengo Jan 21 '19 at 13:41
  • Hi, @Cris Luengo. I got ImageDescription tag from a svs file, there was no key-value pair named resolution. But I found that there is "MPP = 0.5030". This could be the resolution value? or should I read another tag ? – YJJ Jan 21 '19 at 14:14
  • @YJJ: Yes, that’s the one. It stands for “Micron Per Pixel”. – Cris Luengo Jan 21 '19 at 14:15
  • @YJJ: no, a micron is tiny. There are 10,000 of them in each cm. 0.5 micron = 0.000,5 mm = 0.000,05 cm. You can use Google to convert units like these is you’re not certain. Search for “0.5 micron in cm”. – Cris Luengo Jan 21 '19 at 15:23
  • 0.000,05 cm per pixel seems extremely small. is it valid value for a resolution? – YJJ Jan 21 '19 at 15:48
  • @YJJ: Yes. It's a microscope. Of course it's small. That's the point of a microscope... Say the slice of tissue scanned is 2 cm wide. Thus you get 2.0 cm / 0.000,05 cm/pixel = 40,000 pixels. Does that sound about right? – Cris Luengo Jan 21 '19 at 15:52
  • Oh I see. the resolution level is incredible. Thank you always for answering me many times. You definitely help me a lot. I appreciate it. – YJJ Jan 21 '19 at 16:10
0

You can read out the thumbnail image (is this what you mean by whole scale image?) as an openslide associated image.

For example, libvips has a convenient openslide binding written by the openslide authors:

$ vipsheader -f slide-associated-images CMU-1.svs
label, macro, thumbnail

Lists the images in the SVS file. macro is the huge pyramid that you get by default, thumbnail is the small overview, label is the shot of the slide label.

Get the thumbnail like this:

$ vips copy CMU-1.svs[associated=thumbnail] x.jpg

To read as a JPG image.

In C++, you could write:

VImage thumb = VImage::new_from_file("CMU-1.svs", 
    VImage::option()->set("associated", "thumbnail"));
thumb.write_to_file("x.jpg");
jcupitt
  • 10,213
  • 2
  • 23
  • 39