Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Error: VipsForeignLoadJpegFile does not support optional argument level #318

Closed
jeremyEudaric opened this issue Apr 4, 2022 · 34 comments
Closed

Comments

@jeremyEudaric
Copy link

jeremyEudaric commented Apr 4, 2022

Hello,
l m trying to get my image like a pyramidal tiff on level 0. So my images are on the format 'jpeg' and l want to them on "tif" format with the level zero.
So l did :

import pyvips as pv
pv = pv.Image.new_from_file("/Users/eudari01/GNNs_Vs_CNNs/test/1.jpg", level=0)
pv.tiffsave('1.tif', compression= 'jpeg', pyramide= True, title = True)

and l got the error, VipsForeignLoadJpegFile does not support optional argument level.

my question is the next one. How can l have a level (0) in my images ?

Many thanks

@jcupitt
Copy link
Member

jcupitt commented Apr 4, 2022

Hi @jeremyEudaric,

JPEG is not a pyramidal format --- it's always a simple, flat file. This means there are no levels to pick from.

Try:

import pyvips

image = pyvips.Image.new_from_file("/Users/eudari01/GNNs_Vs_CNNs/test/1.jpg", access="sequential")
image.tiffsave('1.tif', compression="jpeg", pyramid=True, tile=True)

The access="sequential" will let libvips stream the image from the source JPEG, rather than decoding the whole thing in advance.

@jeremyEudaric
Copy link
Author

hello thank you ! So its not possible to add a level on a JPEG images with pyvips ? l wondering that because all my images are on JPEG format and l am using a specific library which need to get images with a level=0.
So regarding the previous question its ok now thank you ! l did the conversion.

However when l am using my specific library l get the error message Error: VipsForeignLoadTiffFile does not support optional argument level.
so its mean that all my images need to have a level, to use this library

many thanks for your helps !

@jcupitt
Copy link
Member

jcupitt commented Apr 5, 2022

No, JPEG images do not have levels, it's not possible.

Maybe you mean a TIFF image with JPEG compression?

@jeremyEudaric
Copy link
Author

Yes , a TIFF image with JPEG compression? Convert JPEG image to TIFF.
many thanks for your helps !

@jcupitt
Copy link
Member

jcupitt commented Apr 5, 2022

Pyramidal TIFF images store their levels in one of two ways -- either as pages of the document, or using subifds.

A page-based TIFF pyramid stores the pyramid with the full resolution image in page 0, the half-resolution level in page 1, and so on. Use something like:

level = pyvips.Image.new_from_file("xxx.tif", page=2)

To load a specific page. By default, libvips will load the full resolution image, so:

level = pyvips.Image.new_from_file("xxx.tif")

Will get you page 0.

subifd pyramids are more complicated: they use a TIFF subdirectory to store the lower resolution levels. Hopefully you don't have one of these.

@jeremyEudaric
Copy link
Author

jeremyEudaric commented Apr 5, 2022

okey thanks ! if l am doing "level = pyvips.Image.new_from_file("xxx.tif")" , my image will be an pyvips object and not usable in input of a CNNs for example. My idea is to convert my jpeg image in a " tif" format ( with a level 0) and after that use it as input of my model

many thanks for your help!

@jcupitt
Copy link
Member

jcupitt commented Apr 5, 2022

What are you using to build the model? You can get a numpy array from a pyvips image and use that.

@jcupitt
Copy link
Member

jcupitt commented Apr 5, 2022

@jeremyEudaric
Copy link
Author

to build my model l am using pytorch to build my CNNs. Unfortunately l can not use my image as numpy array because l need to do a preprocessing on my images and l can not do it with an array . l mean l need to split my images in tiles. And to do this l use a framework but this framework can only use in input images with a level = 0. So my wish is to convert my JPEG images to tif and get a level 0.

@jeremyEudaric
Copy link
Author

jeremyEudaric commented Apr 7, 2022

Hello, sorry l didn't understood well the first answer. l want to get jpeg images into a pyramidal file format that is not jpeg - like pyramidal tiff. How can l do that.
l used this itd's doesnt works :

import pyvips

image = pyvips.Image.new_from_file("/Users/eudari01/GNNs_Vs_CNNs/test/1.jpg", access="sequential")
image.tiffsave('1.tif', compression="jpeg", pyramid=True, tile=True)

many thanks

@jcupitt
Copy link
Member

jcupitt commented Apr 7, 2022

It should work. Is there an error message? Does it write a file?

@jcupitt
Copy link
Member

jcupitt commented Apr 7, 2022

You can also use the command-line:

vips copy my-test-image.jpg output-image.tif[tile,pyramid,compression=jpeg]

@jeremyEudaric
Copy link
Author

yess its working , so l get a tif image. However when l'm using the new image ( in tiff format ) on my frameworks , l get the error message Error: VipsForeignLoadTiffFile does not support optional argument level.
So l guess my frameworks doesn't support, "fake" tif format images ? It's strange

@jcupitt
Copy link
Member

jcupitt commented Apr 8, 2022

Error: VipsForeignLoadTiffFile does not support optional argument level.

You need to use page to pick out TIFF pages, see my note above ^^

@jeremyEudaric
Copy link
Author

hello so l did that :
image = pyvips.Image.new_from_file("1666.jpg", access="sequential")
image.tiffsave('1666.tif', compression="jpeg", pyramid=True, tile=True)
level = pyvips.Image.new_from_file("1666.tif", page=2)

But like l said previously l would like my image not like an object or an array but like a new image on a tif format so , l need to re save a new image with "level = pyvips.Image.new_from_file("1666.tif", page=2)" but it doesn't works. l used "tiffsave" a second time. Do yo have an idea ? many thanks

@jeremyEudaric
Copy link
Author

okey thanks ! if l am doing "level = pyvips.Image.new_from_file("xxx.tif")" , my image will be an pyvips object and not usable in input of a CNNs for example. My idea is to convert my jpeg image in a " tif" format ( with a level 0) and after that use it as input of my model

many thanks for your help!

this :)

@jcupitt
Copy link
Member

jcupitt commented Apr 12, 2022

Sorry, I don't understand what you want to do.

You have created a jpeg-compressed TIFF pyramid. Isn't that what you need? What system are you trying to pass this into?

@jeremyEudaric
Copy link
Author

jeremyEudaric commented Apr 12, 2022

So l get a tif image, with this image = pyvips.Image.new_from_file("1666.jpg", access="sequential")
image.tiffsave('1666.tif', compression="jpeg", pyramid=True, tile=True)
So l have created a jpeg-compressed TIFF pyramid. So normally now l get an image on the format tif right ?

However when l'm using the new image '1666.tif' ( in tif format ) on my framework https://github.com/markowetzlab/slidl-tutorial ( its a framework to split the images in tiles)
, l get the error message Error: VipsForeignLoadTiffFile does not support optional argument level.

So l guess my frameworks doesn't support, "fake" tif format images ?

Many thanks :)

@jeremyEudaric
Copy link
Author

jeremyEudaric commented Apr 12, 2022

l only want a jpeg-compressed TIFF pyramid ( with a level 0) and save this image to use it after in input of my model. l hope my questions are clear . Sorry about that , again many thanks for your support

@jcupitt
Copy link
Member

jcupitt commented Apr 12, 2022

Oh, the message is from this other software, not from your code? Now I see.

This other software is expecting an SVS image, not a TIFF. You'll need to adapt it. I would open an issue on that repo.

@jeremyEudaric
Copy link
Author

jeremyEudaric commented Apr 12, 2022

normally the software should take a TIFF as well.
its no possible to do this :
image = pyvips.Image.new_from_file("1666.jpg", access="sequential")
image.tiffsave('1666.tif', compression="jpeg", pyramid=True, tile=True)
level = pyvips.Image.new_from_file("1666.tif", page=2)
An after save the new TIFF image with a page = 2, like an image not like a array or an object ?

@jeremyEudaric
Copy link
Author

Hello sorry for all my question but for its look like a circle :/ because when l did :

mage = pyvips.Image.new_from_file("1666.jpg", access="sequential")
image.tiffsave('1666.tif', compression="jpeg", pyramid=True, tile=True)

l got a new image "1666.tif" but if check this image she is like the previous one, l mean its like only the name change but the format doesn't .

And the new image doesn't work on my software but normally its should be ok , because the software can get in input all the format ( excepted JPEG)

l only want a jpeg-compressed TIFF pyramid ( with a level 0) and save this image to use it after in input of my model. Otherwise , how can l convert my JPEG image to SVS.

Thank you for your help !

@jcupitt
Copy link
Member

jcupitt commented Apr 13, 2022

The message Error: VipsForeignLoadTiffFile does not support optional argument level. means some software (I guess your ML framework) has this line of code:

image = pyvips.Image.new_from_file(filename, level=some_number)

It is expecting to read an SVS image (loaded via openslide, which does have a level parameter), but you are passing a TIFF image (which does not have a level parameter).

You need to fix this error in your machine learning framework. I would open an issue there.

@agberman
Copy link

agberman commented May 4, 2022

Hi, I have a couple questions related to this: doesn't pyvips.Image.new_from_file() accept pyramidal tiffs? If so, isn't the image created above a pyramidal tiff with a single level? Or, does it have one level but it simply isn't called "level" in the file metadata? If so, is there a pyvips argument to read in a specific level of a pyramidal tiff? For example, for pyramidal tiffs, does something like image = pyvips.Image.new_from_file(filename, pyramidal_tiff_level=some_number) work instead?

Another question I have is, is there a way to convert a flat jpg to an SVS with a single level? So instead of converting to a pyramidal tiff, converting to an SVS with one level (level 0)?

@jcupitt
Copy link
Member

jcupitt commented May 4, 2022

Hi @agberman, all new_from_file does is call vips_foreign_find_load(filename) to detect the file format, then run that loader.

https://www.libvips.org/API/current/VipsForeignSave.html#vips-foreign-find-load

So for a TIFF, that'll return "tiffload", and then new_from_file will run that, passing in all the parameters. For tiffload, use the page= parameter to select pages (ie. pyramid levels).

SVS images are loaded by openslideload, so you need to make sure you have a libvips with openslide support compiled in. If you don't, libvips will fall back to using tiffload, and it won't open correctly.

openslideload uses the level= parameter to select the pyramid level.

You can only read SVS images, you can't write them. I would convert to a tiled tiff with JPEG compression (this is roughly what SVS is internally).

@jeremyEudaric
Copy link
Author

Hi thank you for your response. So it mean that is not possible to convert a Jpeg image into a SVS format ( with 3 levels). We are using Whole Slide Images and apparently they data we got doesn't a level into ( usually Whole Slide Images has 3 levels but in our case not due to the JPEG format).

An other solution could be add on the raw images a level . we have all the informations to do this (positions etc), do you know a good software ?
Thank you very much

@jcupitt
Copy link
Member

jcupitt commented May 5, 2022

No, openslide will not write slides, it will only read them. This means you cannot write SVS slides.

I convert SVS slides to tiled pyramidal jpeg TIFF for viewing, since (as you say) SVS slides are missing half of their pyramid layers and perform very badly.

I'm not sure I understand what you mean by JPEG images. SVS slides are TIFFs with JPEG compression, but with missing levels.

@jcupitt
Copy link
Member

jcupitt commented May 5, 2022

Maybe there is some confusion about image formats here? We are discussing three different formats:

  1. JPEG images have just width x height pixels. There are no tiles and no pyramid levels.
  2. TIFF has many variations, but one is pyramidal and tiled, with JPEG compression for each tile. libvips can read and write these. Use page=xxx to pick a pyramid level in pyvips.
  3. Leica have their own variant of TIFF with tiles and JPEG compression. libvips uses openslide to read these. Use level=xxxx to pick a level.

Sadly, type (3) is missing half the pyramid levels, so performance for zooming is very bad. It's best to convert images like this into type (2) for viewing. libvips can do this quite quickly with tiffsave.

To convert slow (3) images into fast (2) images, use:

image = pyvips.Image.new_from_file("xxx.svs")
image.write_to_file("yyy.tif", tile=True, pyramid=True, compression="jpeg")

@jcupitt
Copy link
Member

jcupitt commented May 5, 2022

If your ML software is giving you this error with your converted TIFFs:

Error: VipsForeignLoadTiffFile does not support optional argument level.

It is a bug in your ML software. You need to open an issue there.

@jeremyEudaric
Copy link
Author

oh thank you for your help!! Indeed, l had some confusion on images format. l did that but its make no sense because l am trying to convert a image on JPEG format ( with no level ) to a TIFF

image = pv.Image.new_from_file("1645OrginialImage.jpg")
image.write_to_file("1645OrginialImage.tif", tile=True, pyramid=True, compression="jpeg")

My software can only get image with some levels into

@jcupitt
Copy link
Member

jcupitt commented May 5, 2022

Try this, it should be quicker:

image = pv.Image.new_from_file("1645OrginialImage.jpg", access="sequential")
image.write_to_file("1645OrginialImage.tif", tile=True, pyramid=True, compression="jpeg")

What's the problem with the TIFF? You'll need to explain more carefully.

@jeremyEudaric
Copy link
Author

jeremyEudaric commented May 5, 2022

So with the lines of code above a get the new image "16450rginialImage.tif" so l did after :

image = pv.Image.new_from_file("1645OrginialImage.tif",page=0)
image.write_to_file("Image.tif", tile=True, pyramid=True, compression="jpeg")

to pick a pyramid level in pyvips ( with page = 0)
So normally my image has a pyramidal level.
After that l'm using my new image into my ML software ( its should works because now my image get levels)
However l still have the message error

Error: VipsForeignLoadTiffFile does not support optional argument level

@jcupitt
Copy link
Member

jcupitt commented May 5, 2022

However l still have the message error
Error: VipsForeignLoadTiffFile does not support optional argument level

Right, that's because your ML software only works with SVS images. You need to contact the authors and ask them to fix it.

@jeremyEudaric
Copy link
Author

Many thanks for your help !

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants