Updated compilation environment on Windows.

I am not sure you can actually use the generated lib from libgmic on your system, as it has to match compiler versions exactly and you’ll probably also need third-party libraries and headers, but here is the package I just generated (libgmic.lib and other third-party libs like libpng):
http://reduxfx.com/rtmp/libgmic_vs2019.zip

Thanks I don’t have it working yet. I’ll try again tomorrow.

I have now managed to compile the latest sources from the G’MIC develop branch using Visual Studio, including support for OpenMP, FFTW3, CURL (including HTTPS/SSL), PNG, JPEG and TIFF and with full optimisations. Since all libraries are linked statically, the whole gmic.exe file is self-contained and does not need any other DLL to work (apart from the Microsoft runtime if that isn’t installed yet on your system, but event that could be linked statically).

Here is a binary build of the CLI for anyone that wants to test/compare:
http://reduxfx.com/rtmp/gmic_cli_vs2019.zip

3 Likes

I have been able to compile now. It throws lots of warnings but no errors.

Using the example code from here (Step 3) throws an exception on the line:

gmic("water[0] 20 flower[1] 20 blend vividlight", image_list, image_names);

The error message is:

Exception at 0x7ff90daf3b29, code: 0xe06d7363: C++ exception, flags=0x1 (execution cannot be continued) (first chance) in GmicTest2!cimg_library::CImgDisplay::_no_display_exception

Against what display backend have you compiled it? On Windows, it is a good idea to compile against the GDI backend (“cimg_display=2” as a preprocessor define), at least that is what I do.

I had it set to 0, since I need no displaying. Tried it with 2 now but no luck. Still crashes when I want to do something with an image.

Does this work for you?

It’s really strange, because your example should not trigger a display attempt from the G’MIC library. Displaying images at the end of a pipeline is done only when the G’MIC variable $_host is equal to cli which should not happen in your case, if you compile only the libgmic.

Yeah that’s what I thought, that I am not trying to display anything anyway.

I must be doing something wrong, my Windows-fu is not the strongest. Only other idea I have right now is to try again on a VM with a fresh Windows install, just to see if something is wrong with my configuration.

I’ll do that in the next few days when I have the time.

Thank you very much!!! I will look at it when I have less stressed mind in the coming weeks…

You have free windows VMs for developers here Télécharger une machine virtuelle Windows 10 - Développement d’applications Windows
I used the virtual box version and needed virtual box >6.0

Reinstalled my dependencies and it works now! :partying_face:

2 Likes

I spoke too soon.

While I can successfully output an image from my code, the library still causes crashes when I do other things, like loading filters. The error:

Exception at 0x7ff90daf3b29, code: 0xe06d7363: C++ exception, flags=0x1 (execution cannot be continued) (first chance) in Cascade!cimg_library::CImgDisplay::_no_display_exception

I don’t have a good idea how to track this down. libgmic has been compiled without display support (option 0) and I am not using any display-related things in my code.

The last function I can see in the debugger before the crash is gmic::add_commands but I don’t if that says anything about what’s going on.

In case anyone is interested, I did some compiler and speed tests on Windows today using the latest sources in the develop branch and tested the G’MIC CLI.

Let’s start with the compilation stage:

First I compiled the sources using my MinGW/MSYS2 setup using the provided Makefile, no changes. This (unsurprisingly) spit out a gmic.exe that is about the same size as the latest official 2.9.4 binary - a bit over 10 MB. Of course this exe has dependencies on the 23 additional DLLs of the MinGW runtime environment, which clock in at 14+ MB, making the whole distribution package 24 files with around 25 MB in total.

I then compiled the sources with my Visual Studio 2019 solution with optimization enabled in MT mode (static linking of the Microsoft C++ runtime). The result was also around 10 MB for the exe, but this one is self-contained, meaning it does not need any additional DLLs to function, not even the Visual Studio or C/C++ runtime environment. The only thing it needs (since it was compiled with OpenMP enabled) is Windows’ own vcomp140.dll OpenMP library, which should be present on modern systems anyway.

All three files (the official binary, my MinGW/gcc one and my Visual Studio one) have the same featureset enabled (including CURL with https/SSL support, png, jpg, tiff, fftw3 and OpenMP) and seem to behave the same functionwise, so in the next step, I looked at the speed:

For this I used a heavy processing command (fx_stylize) and even applied it on a big 4K image to really put the system under stress:
gmic -tic -input 4k.bmp _fx_stylize starrynight +fx_stylize 1,6,0,0,0.5,2,3,0.5,0.1,3,3,0,0.7,1,0,1,0,5,5,7,1,30,10,2,1.85,0 -output 4k_out.bmp -toc
Well, the results took some time, as expected, but all three spit out a similar looking image with the style applied:

Concerning speed, on my 10-year old notebook, I ran each test 3 times with each of the three binaries, here are the averaged times for each:
Original CLI (MinGW/gcc): 672 seconds
My CLI (MinGW/gcc): 520 seconds
My CLI (VS 2019): 340 seconds

So interestingly, the Visual Studio version is (at least for this command and on my system) around twice as fast as the gcc one, while only being one third in size. Why my MinGW/gcc compiled binary was also almost 2 minutes faster than the original one - I have no idea.

In case anyone wants to test against my VS binary, I uploaded it here:
http://reduxfx.com/rtmp/gmic_cli_294_vs2019.zip

2 Likes

Very interesting, and to be honest, I’m not so surprised by the timing difference between gcc and VS2019. I know that other open source projects are also compiled with VS, to avoid performance issue (Krita is one of them).

I’d be really interested by binary packages on Windows, equivalent to what I propose on the web page, but compiled with VS2019. I don’t really have time to go into this unfortunately.

The main challenge with static builds is that you need all the other static libs prepared in the same configuration you create your application or library, so if I use VS2019 v16.8 in Release configuration and MT linkage in 64bit, then you need all third party libraries (libpng, libjpeg, libtiff, fftw3, libcurl, zlib, etc.) compiled as static libraries with eactly these settings (and if they are C++ libraries instead of C even with exactly the same compiler version!). This makes it easy for the end-user, since he gets a self-contained executable and does not have to worry about incompatible DLLs, but it is of course rather hard for a developer to set up a compilation environment, since he now also needs to take care of all these additional and often ridiculously complex third-party libraries.
There have been efforts and tools to try to remedy that, e.g. vcpkg and Nuget for Visual Studio, homebrew on MacOS, etc., providing pre-built libraries, but I always ran into problems with those. since it often did not perfectly match my environment, especially when linking lots of different libraries.
And since I am involved in a lot of open-source projects and also many big commercial applications that need regular builds of these libraries, I went the hard route and have made for many, many of these open-source libraries (including all of the above ones) specific Visual Studio solutions to make them build with any VS version in any required configuration.
This can be a bit overwhelming at times, if you for example take one single, self-contained and simple library like libpng: For libgpng, I have scripts for 9 different Visual Studio versions (from VS2008 to VS2019), each having a Debug/Release, 32/64bit, MT/MD, static/shared option, resulting in 144 different libs to build just for this single libpng library! And that was only for one operating system - I keep all of these libraries compilable at least against Windows, MacOS and Linux (the later with CentOS and Ubuntu being the usual targets). And of course I do not want to change the original source files of the library if possible, so if a new version comes out, I can just update the sources and recompile.

The good thing is that many of these third-party libs do not change often or haven’t changed in years, so once you have created the most common builds, you can just leave them as libs to link to, unless you upgrade your compiler or a new version of the library needs to be compiled.
For me it was just the initial effort of doing this, and I now have the most common static and shared libraries available on my build server and if not, I can easily re-create them, making working with projects that require a lot of different libraries so much easier. :slight_smile:

That was also the reason why I proposed the libcgmicstatic back then: to have one self-contained G’MIC library without any dependencies that other developer can easily link to and use without having to worry about compilers, libraries, dependencies, etc. This made integrating G’MIC into other applications so much easier, as you saw in my other posts.

1 Like

Hmm, with some trials on my ill conditioned virtual Windows 10. I don’t see any timing difference between Davids and Tobias built!

gmic.exe osteo tic run “repeat 20 +karo_open[0] {($>+1)*5},1 done” toc rm

At least with this command string!

By the way, under Windows wsl ubuntu 20.04 LTS gmic build from David, this command string needs a third of the Windows executable time!

1 Like

@David_Tschumperle: Visual Studio gives around 300 code analysis warnings and comments (not related to compiling, but rather based on “intelligent” source code analysis).
Some of these seem not too far fetched, e.g. here are some examples from CImg.h:

CImg.h line 6984:
for (char *ns = str, *nd = str; *ns || (bool)(*nd = 0); ++nd) if (ns==’\’) switch ((++ns)) {
→ is the assignment of *nd = 0 really intended to be an assignment and not a comparison?

CImg.h line 11091:
_background_window = CreateWindowA(“MDICLIENT”,"",WS_POPUP | WS_VISIBLE, 0,0,sx,sy,0,0,0,&background_ccs);
→ variable background_ccs is used without being initialized, contains random member values!

CImg.h line 37800: xstride==1 && ystride==1 && ystride==1) {
→ ystride compared twice?

Valid, second ystride should be zstride.

Seems valid too. I guess it should be replaced by NULL.

Not valid, although the code is probably not optimal to do the operation :slight_smile:

Well, no, it makes my program crash… Not sure what is going on there.

No, NULL cannot work, since it needs to be an existing variable so the CreateWindow function can store the handle there.

Just initialize it like this:
CLIENTCREATESTRUCT background_ccs = { 0 };