ruven / iipsrv

iipsrv is an advanced high-performance feature-rich image server for web-based streamed viewing and zooming of ultra high-resolution images.
https://iipimage.sourceforge.io
GNU General Public License v3.0
291 stars 115 forks source link

Add support for PNG output #102

Closed beaudet closed 3 years ago

beaudet commented 7 years ago

I thought there was already an issue created for this, but I'm not able to find it, so creating a new one.

I have this working and will submit a PR for it, but libpng doesn't make it easy to multi-thread the encoding. libpng is about 10x slower than libjpeg in the calls made by CompressStrip. I can either submit a PR for what I have now which works functionally and / or I can spend a little bit of time trying to multi-thread the CVT strip loop so it works with libpng. It's possible that might also speed up jpeg generation, although given the 10x difference, libjpeg might already support multi-threading in the encoding operations.

beaudet commented 7 years ago

Well, it turns out the whole compressor approach isn't really thread safe and I don't have time to completely refactor it right now, so I'm going to submit a PR for the basic PNG functionality. We don't really plan to use png very much and when we do it will be with very small files, so for now, this is good enough for a first step.

beaudet commented 7 years ago

PNG also doesn't seem to support an uncompressed format, so we can't bypass compression in favor of faster processing / larger files. I'm sure it can be multi-threaded, but it will take some work.

beaudet commented 7 years ago

Actually it might. I'll look into png_set_compression_level

beaudet commented 7 years ago

There are two levers that really affect PNG write performance. One is the compression level and the other is a filter that massages the data to better prepare it for compression. Seems that even if the compression level is set to NONE, the filter is still called. Disabling both the compression level and the filter results in a 10x speedup in PNG write performance. However, there's a substantial increase in file size - somewhere in the 80-100% range. I've disabled compression and filters for PNG output to boost performance. I'll add some configuration parameters to let users make the decision about whether to select file size or compression speed. Since we will only be using PNGs for small thumbnails, I'm not concerned about file size at all and I think this is probably the best default option.

beaudet commented 7 years ago

@ruven, I have this ready to issue a pull request. Do you want me to issue it against your MASTER or do you want to create a development branch first?

ruven commented 7 years ago

Thanks for this! I've just created a png branch, so issue a pull request to that.

For compression, we can reuse the existing QLT parameter to provide user-level control. For server-side configuration, we can add a PNG version of the JPEG default quality level and a switch for enabling/disabling the filter.

If I also implement the missing tile export functions we should have a complete PNG solution!

beaudet commented 7 years ago

Will do @ruven. Will you be creating a develop branch as well for the lanczos filter and resubmissions of the cache enhancements or separate branches for those as well?

ruven commented 7 years ago

I've made separate lanczos and cache branches for you

beaudet commented 7 years ago

Thanks, I'll target those. Are you planning on merging all of those branches together with an experimental development branch? It would make my life easier to have access to a remote repository that I know contains all of these merged changes since that's the version we'll be using. If not, I'll have to manage that locally I guess until they are incorporated into master.

beaudet commented 7 years ago

We need a server side control for the actual PNG filter in order to provide adequate control on IIIF quality. I also supplemented QLT that could be used with a future PTL command. I checked with the IIIF community and there was debate about 3 years ago and they deferred discussion of a compression quality parameter due to lack of use cases. I see their point. The spec doesn't prevent IIP from handling a custom IIP quality selector such as default.90.jpg or default.PNG_FILTER_SUB although that would require clients to make use of it. So, I think having control over the quality at the server level is sufficient for the vast majority of uses. That's not to say that the IIP protocol and client wouldn't be able to make immediate use of PNG and associated QLT settings.

billhill00 commented 7 years ago

Just noticed this pull request. I was just about to start merging our PNG support back into iipsrv. I'm sorry for being so slow and wasting effort. It's probably to late now, but if it's of any use, we've code that does this too (WlzIIPSrv PNGCompressor).

beaudet commented 7 years ago

@ruven Do you need me to update the PR after getting in sync with your master branch or are you working on the PNG PTL and other functions before merging?

ebremer commented 7 years ago

Any ETA on png support in IIP? I have images with alpha channels which I need preserved when sent to the client.

ruven commented 7 years ago

PNG support is on it's way, but I don't think there'll be alpha channel support initially.

ebremer commented 7 years ago

It would be terribly useful. Is there a technical reason that prevents the addition of the 4th channel in the png at this time?

ebremer commented 6 years ago

What is the status of png support in IIP?

beaudet commented 6 years ago

I have it working in production from the nga_prod branch of my iip fork, but not with an alpha channel. e.g. https://media.nga.gov/iiif/public/objects/5/0/7/2/4/50724-primary-0-nativeres.ptif/full/!,600/0/default.png

I did this for IIIF image API compliance reasons not because we're actually using PNGs on web sites and the like. It might make sense for us to use PNGs for embedding in PDFs or creating other highest possible quality documents though.

arthur-flam commented 5 years ago

Hi @beaudet, Thanks a lot for your work adding png support. Lossless outputs will be very useful to us. Could you tell us about the status of your [nga_prod branch(https://github.com/beaudet/iipsrv/tree/nga_prod)? I understand that's where the most up-to-date png support is found. Do you think I could even merge the latest changes on master without surprises? @ruven: Do you think PNG support could be merged? Btw, I must also extend my thanks to you: we were able to add a custom decoder very easily, and iipsrv works great.

ruven commented 5 years ago

Hi @arthur-flam, glad iipsrv is working great for you! For PNG support, yes, this will definitely be integrated and will certainly be in the next iipsrv 1.2 release.

arthur-flam commented 5 years ago

Great news! Thanks a lot! :+1:

beaudet commented 5 years ago

@arthur-flam - I added in support for PNG mainly to comply with the IIIF Image Spec 2.1 - it works fine without compression enabled. With lossless compression enabled, the process crashes in certain situations and I never had a chance to track that down. By all means feel free to fork the latest PNG work and create an updated PR for it as it's unlikely I'll have time to do that in the near future. I'm not sure how much it's changed since the initial PR and there's been a server release since the PR was created.

arnocertic commented 5 years ago

Hi @beaudet We are interesting by this PNG support too. Is this PNG support still without the 4th alpha channel ? Thks Arnaud

beaudet commented 5 years ago

@arnocertic - correct. Is your use case addressed by the approach outlined here: https://github.com/openseadragon/openseadragon/issues/1397

arnocertic commented 5 years ago

@beaudet I will have a try, many thanks for the link.

ruven commented 3 years ago

OK, PNG support now available: https://github.com/ruven/iipsrv/commit/7cf3457461ffd403d5d8cd8b1b5f82e808cb95bb

It supports tile output through the IIP PTL command as well as through IIIF requests and also handles alpha channel transparency. The code also handles 16 bit PNG output (but this isn't yet activated as it needs the whole processing pipeline to be modified).

Please test it out and get back to me if you find any problems.

PS: Thanks @beaudet for your work on your earlier implementation.