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

Add experimental JPEG 2000 support with OpenJPEG #61

Closed
wants to merge 13 commits into from

Conversation

stweil
Copy link
Contributor

@stweil stweil commented Mar 17, 2016

This pull request is for broader tests and further discussion.

@boxerab
Copy link

boxerab commented Mar 30, 2016

+1 for this PR

@ahankinson
Copy link
Contributor

I'm wondering if OpenJPEG support should be enabled with a flag on the configure command rather than as an environment variable.

@ruven
Copy link
Owner

ruven commented Mar 30, 2016

I'm wondering if OpenJPEG support should be enabled with a flag on the configure command rather than as an environment variable.

Yes, I agree. Apart from for development testing purposes, I don't really see the need to be able to switch between codecs in this way. So, it would make more sense for the choice of JPEG2000 codec to be determined at the configure stage.


if(!(fsrc = fopen(filename.c_str(), "rb"))) throw string("ERROR :: OpenJPEG :: openImage() :: failed to open file for reading");
filename = getFileName( currentX, currentY ); // Get file name
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My C++ is rusty, but shouldn't there be a type definition string here?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, sorry -- apparently this was superceded...

@stweil
Copy link
Contributor Author

stweil commented Mar 30, 2016

I consider OpenJPEG support to be experimental. If there are no Kakadu files available, the build simply produces a server working with OpenJPEG (no need to set an environment variable). If Kakadu files are available, then this must be the default for compatibility reasons and because it is still much faster, but of course it must also be possible to test OpenJPEG. That's why I added the environment variable.

Would it be better to select Kakadu / OpenJPEG via an URL option? Then it would be possible to compare both on the fly (without running two servers or restarting a single server with different environment settings)?

@ruven
Copy link
Owner

ruven commented Mar 30, 2016

but of course it must also be possible to test OpenJPEG

It's much cleaner to do this by enabling (or disabling) the choice of decoder through the configure script. Sure, at the moment, Kakadu should be the default if available. If you want to test, you can always build a server with each decoder and run them in parallel, allowing you to compare them.

@stweil
Copy link
Contributor Author

stweil commented May 18, 2016

@ruven, which coding style do you prefer for iipsrv? I noticed that the new files for OpenJPEG seem to use a different style (indentation with tabs, function brackets at line endings and more differences) and would like to add a patch which fixes the coding style.

@stweil
Copy link
Contributor Author

stweil commented May 20, 2016

I rebased the PR and added three patches which fix compiler warnings.

@stweil
Copy link
Contributor Author

stweil commented May 20, 2016

Now a patch which formats the code was added.

@calvinbutcher
Copy link

+1 for this PR

@stweil
Copy link
Contributor Author

stweil commented May 26, 2016

@acdha, was your last emoji intentional? What is wrong with the pull request?

@acdha
Copy link

acdha commented May 26, 2016

@stweil Sorry – I've been developing an allergy to "+1" comments but I should have stayed quiet about it

@stweil
Copy link
Contributor Author

stweil commented May 26, 2016

@ruven, are you planning own code for OpenJPEG support, or do you want to use the code from this PR? If the later: is there anything which should be changed before pulling? I'm asking because I have more modifications for that issue in my queue. I can add them here if this is useful.

@ahankinson
Copy link
Contributor

Has the environment variable / compile flag issue been addressed?

@stweil
Copy link
Contributor Author

stweil commented May 28, 2016

The current code still supports builds which support both Kakadu and OpenJPEG, with preference for Kakadu at run time and possible selection of OpenJPEG via environment. As without my PR, Kakadu needs to be configured explicitly. OpenJPEG is compiled automatically if it is found. The advantage of the current code is that Kakadu users will get Kakadu as usual and all other users will get OpenJPEG automatically. This also ensures best code coverage for the compilation (no code rotting) without the need for multiple builds.

I have new commits in my local tree which add a configure option for OpenJPEG as well. Thus both Kakadu and OpenJPEG have to be enabled during configuration.

@boxerab
Copy link

boxerab commented May 28, 2016

Unfortunately, OpenJPEG doesn't have true region decoding, so it will always be quite slow.
True region decoding only decodes code blocks that lie within a region, plus boundary, and ignores everything else. One solution is to tile the image with relatively small tiles : 256x256 for example. But, there may be artifacts.

@stweil
Copy link
Contributor Author

stweil commented May 28, 2016

For whole images, the current OpenJPEG support for iipsrv is slow because of incomplete / old code (missing functions regionDecoding and old signature of OpenJPEGImage::getRegion). Depending on the image size, an improvement by a factor of 100 and more can be reached when fixing that.

These files from git@github.com:moravianlibrary/iipsrv-openjpeg.git
are needed to support JPEG 2000 using libopenjpeg instead of Kakadu.

Information from the original commit:

commit 9262068b8606c2a0699ee74fad4ec991d34c7715
Author: Daniel Secik <dsecik@gmail.com>
Date:   Tue Jun 9 18:04:46 2015 +0200

    Initial commit

Signed-off-by: Stefan Weil <sw@weilnetz.de>
* Remove whitespace at line endings

* Remove empty line at end of file

Signed-off-by: Stefan Weil <sw@weilnetz.de>
See this discussion:
moravianlibrary/iipsrv-openjpeg#1

Signed-off-by: Stefan Weil <sw@weilnetz.de>
* Update OpenJPEGImage::openImage for latest iipsrv.

Signed-off-by: Stefan Weil <sw@weilnetz.de>
* Add check for OpenJPEG JPEG2000 library (code mainly from
  moravianlibrary/iipsrv-openjpeg).

* Use Kakadu by default (if available). OpenJPEG can be enforced by
  setting the environment variable USE_OPENJPEG=1.

Signed-off-by: Stefan Weil <sw@weilnetz.de>
gcc reports these warnings:

src/OpenJPEGImage.cc:174:14: warning:
 comparison between signed and unsigned integer expressions [-Wsign-compare]
  for(; tmp_w > tile_width || tmp_h > tile_height; ++i){
              ^
src/OpenJPEGImage.cc:174:36: warning:
 comparison between signed and unsigned integer expressions [-Wsign-compare]
  for(; tmp_w > tile_width || tmp_h > tile_height; ++i){
                                    ^
As raster_width, raster_height, tile_width and tile_height all are
unsigned values, tmp_w and tmp_h should also be unsigned.

Signed-off-by: Stefan Weil <sw@weilnetz.de>
gcc reports these warnings:

src/OpenJPEGImage.cc:241:7: warning:
 variable ‘edge_x’ set but not used [-Wunused-but-set-variable]
  bool edge_x = false; // Alter the tile size if it's in the last column
       ^
src/OpenJPEGImage.cc:247:7: warning:
 variable ‘edge_y’ set but not used [-Wunused-but-set-variable]
  bool edge_y = false; // Alter the tile size if it's in the bottom row

Signed-off-by: Stefan Weil <sw@weilnetz.de>
Signed-off-by: Stefan Weil <sw@weilnetz.de>
@boxerab
Copy link

boxerab commented Jun 1, 2016

cool. Thanks.

@calvinbutcher
Copy link

Great, that's compiled now..

@calvinbutcher
Copy link

calvinbutcher commented Jun 1, 2016

@stweil , @boxerab Thanks a lot, it works! I'll tidy up my docker images and they should be stable shortly. Thanks again :)

PS. Is it possible to get a tagged release of stweil/iipsrv and Grok?

calvinbutcher added a commit to bodleian/iipsrv-grok-docker that referenced this pull request Jun 1, 2016
@calvinbutcher
Copy link

Now building and testing w/ Loris..

calvinbutcher added a commit to bodleian/loris-grok-docker that referenced this pull request Jun 1, 2016
@stweil
Copy link
Contributor Author

stweil commented Jun 1, 2016

@calvinbutcher, may I use your docker images on Monday next week at ELAG 2016?

@calvinbutcher
Copy link

calvinbutcher commented Jun 1, 2016

@stweil By all means, though I'd keep an eye on the docker hub builds. The openjpeg builds are stable (https://hub.docker.com/r/bdlss/iipsrv-openjpeg-docker/builds/ and https://hub.docker.com/r/bdlss/loris-openjpeg-docker/builds/)

However, the iipsrv-openjpeg image relies on an untagged release of stweil/iipsrv. Only the loris-openjpeg image is stable with tagged releases of OpenJPEG and Loris.

If you can give me a tagged release of your iipsrv, I can put this in and test over the next day or so. It would simply make it more stable.

Regarding the rest, I'm still having a little teething trouble with the iipsrv-grok docker image but I hope this to be sorted very soon.

The loris-grok image: I still don't know yet if it's going to work. But again, I hope this will be sorted one way or the other in a day or two.

@boxerab a tagged release of Grok 1.0 as it stands would make these, when finished, more stable.
Please also remember that the iipsrv-grok build is relying on an untagged release of stweil/iipsrv (as mentioned above).

Sorry this reply is a bit wordy. In summary, tagged releases of Grok and stweil/iipsrv would help make these images more stable for use.

Finally, I'd steer clear of the validation as apparently version 1.0.0 is out of whack with IIIF 2.0. It fails 7 out of 21 tests.

@stweil
Copy link
Contributor Author

stweil commented Jun 1, 2016

Here is your tag: openjpeg-20160529.

@calvinbutcher
Copy link

calvinbutcher commented Jun 1, 2016

Nice, thank you :) I'll put that in both openjpeg and grok builds now.. Done, awaiting builds.

@calvinbutcher
Copy link

@stweil just a heads up, someone here had some trouble rolling them out with vagrant. I'm using a virtualbox instance of Ubuntu 14.04 desktop. I've not had time to look into why.

@calvinbutcher
Copy link

OK, iipsrv-openjpeg and loris-openjpeg builds are stable.

I'm still working on the grok builds. Looks like Pillow doesn't like Grok. I just need to strip out the validation/Pillow requirement for iipsrv-grok and it'll be fine. That'll kill the loris-grok build, though.

@ruven
Copy link
Owner

ruven commented Jun 1, 2016

I've done some preliminary testing with your openjpeg-work branch with iipsrv (changing the default tile size to 256 to make it comparable to the Kakadu implementation) and for an image of size 7185x6217, doing tile requests (JTL command), I get similar timing results to those reported above:

OpenJPEG: 428815
Grok: 313610
Kakadu: 112162

So, Grok is around 3x slower, while standard OpenJPEG is 4x slower than Kakadu. Where performance degrades significantly with respect to Kakadu is with larger images. However, for a larger image of size 15016x11741, I get:

OpenJPEG: Crash!
Grok: 2845229
Kakadu: 124437

So, standard OpenJPEG is unusable, whereas Grok (I guess because of the region decoding that @boxerab added) works, but is around 20x slower than Kakadu, which has a similar decode time to smaller images. Note that these are the decode times for the core process() command in the OpenJPEGImage and KakaduImage classes in iipsrv.

And to put all this into perspective, the same 15016x11741 image in TIFF format has a tile decode time of only 2445, so even Kakadu is significantly slower than TIFF by about a factor of 50!

@stweil
Copy link
Contributor Author

stweil commented Jun 1, 2016

OpenJPEG has problems with large images, see for example uclouvain/openjpeg#730. Can I get your test image somewhere?

@boxerab
Copy link

boxerab commented Jun 1, 2016

@ruven thanks for testing. For large images, what do you think is a good target speed ratio relative to Kakaudu? Something greater than 1 :) @calvinbutcher I will create a tag. @stweil Ruven's test image is only 165 MB, so this is below the 1GB cutoff. I did do a fair bit of memory optimization in Grok, so it does use quite a bit less memory than OpenJPEG.

@stweil
Copy link
Contributor Author

stweil commented Jun 1, 2016

Ruven's test image is only 165 MB, so this is below the 1GB cutoff.

That's why I am interested to know what caused the crash (and to fix it, of course).

@calvinbutcher
Copy link

calvinbutcher commented Jun 2, 2016

@boxerab Thanks. If they're going to be used at ELAG, this will make the docker images more stable.

@ruven
Copy link
Owner

ruven commented Jun 2, 2016

Can I get your test image somewhere?

This particular one, no. But there's nothing special about it. It was converted from tiff using Kakadu with parameters including a precinct size of 256x256, a code block size of 64x64 and RPCL ordering.

That's why I am interested to know what caused the crash (and to fix it, of course).

In fact it was more a memory allocation problem than a seg fault type crash. I guess OpenJPEG tried to put the whole image into memory rather than just a region.

@calvinbutcher
Copy link

@stweil
https://github.com/bodleian/loris-openjpeg-docker
https://github.com/bodleian/iipsrv-openjpeg-docker
https://github.com/bodleian/iipsrv-grok-docker

The above are now stable with tagged releases of stweil/iipsrv and grok, so they should be reliable. Am still working on the loris-grok build but may be fixed by the end of play today.

@boxerab
Copy link

boxerab commented Jun 4, 2016

@stweil this image will give you similar characteristics to Ruven's test image. And, if you decode a small region and compare Kakadu to the open source codecs, Kakadu is truly orders of magnitude faster. So, there is still quite a bit of catching up to do.

@boxerab
Copy link

boxerab commented Jun 5, 2016

By the way, folks, I just discovered a bug in Grok's region decoding : the codec was performing the discrete wavelet transform for the entire image, rather than only for the region. This makes a big difference for large images. So, the latest version on master is now significantly faster when decoding a relatively small region inside a large single-tile image.

@boxerab
Copy link

boxerab commented Jul 8, 2016

Hi Ruven,

Do you think this PR is ready for merging, or is there more work to be done?
Just curious.

I think once it is merged in, we can get people testing it, and this will help identify areas for
improvement, mostly related to higher performance.

Thanks,
Aaron

@ruven
Copy link
Owner

ruven commented Jul 8, 2016

I'm happy to merge this, but if I understood @stweil correctly, this PR is not in fact the latest version:

@ruven: The latest version (not the one in the PR) needs ./configure --enable-openjpeg. The test was made with two different iipsrv.fcgi files – no environment settings involved.

@stweil, are you ready to update or do a new pull request?

@stweil
Copy link
Contributor Author

stweil commented Jul 9, 2016

@ruven, my latest code is now in PR #74. It adds the --enable-openjpeg option for configure and region decoding for full images. The new code is nearly identical to my latest tagged version openjpeg-20160529, but uses the default tile size of 256 and disabled debug code.

@boxerab
Copy link

boxerab commented Jul 20, 2016

I guess this PR could be closed now ?

@boxerab
Copy link

boxerab commented Jul 20, 2016

@calvinbutcher hope you are enjoying the sun and cider. I just fixed a serious concurrency issue in Grok codec; should I move the tag so that docker image gets the bug-fixed version?

@stweil
Copy link
Contributor Author

stweil commented Jul 20, 2016

Closing this PR. It is superseded by PR #74 (which will hopefully be merged soon).

@stweil stweil closed this Jul 20, 2016
@stweil stweil deleted the pr-openjpeg branch September 14, 2017 10:09
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

Successfully merging this pull request may close these issues.

6 participants