easymodo / qimgv

Image viewer. Fast, easy to use. Optional video support.
GNU General Public License v3.0
2.41k stars 169 forks source link

[Question] Windows release with avif/jpegxl support? #295

Closed eddiezato closed 3 years ago

eddiezato commented 3 years ago

Is there any chance to get new windows release with avif/jpegxl support in near future? 😉

easymodo commented 3 years ago

Hi

Fixing bugs atm. mostly done

Avif maybe, unless it requires alot of heavy dll's. In that case i'll provide an optional package with image plugins.

eddiezato commented 3 years ago

If it helps, Nomacs works fine with this dll https://github.com/novomesk/qt-avif-image-plugin

easymodo commented 3 years ago

Yeah i've seen that. Meanwhile you can just put the dll in qimgv's imageformats folder. Most likely will work

eddiezato commented 3 years ago

There is jpeg-xl plugin as well https://github.com/novomesk/qt-jpegxl-image-plugin But they don't work with qimqv, I think because of Qt version. 5.12.4 in qimqv against 5.14.2 of plugins.

So, if only qimqv was built with 5.14.2 Qt and knew about the .avif/.jxl file types to open and index, then it would work. I guess. :)

novomesk commented 3 years ago

Those DLLs work for nomacs because they are build with MS compiler like nomacs. In order to build plugin for qimgv, mingw compiler from MSYS2 platform must be used.

eddiezato commented 3 years ago

@novomesk can you make instructions for building a jxl plugin with msys2?

easymodo commented 3 years ago

@novomesk You had it built with msys2/mingw right? Can you please try decoding this sample

djxl ./sample1.jxl out.png

I keep getting segfaults every time

jxl-crash.zip

novomesk commented 3 years ago

@easymodo I'll try again with MSYS2 next week.

The samples (sample1.jxl sample2.jxl) works on Linux for me.

eddiezato commented 3 years ago

@easymodo I build cjxl/djxl with msys2/mingw myself, the samples decode fine.

But I can't figure out how to build qt-jpegxl-image-plugin with msys2/mingw

novomesk commented 3 years ago

Here are my steps how to build on MSYS2:

pacman -S --needed base-devel mingw-w64-x86_64-toolchain
pacman -S msys/git
pacman -S mingw64/mingw-w64-x86_64-cmake
pacman -S mingw64/mingw-w64-x86_64-qt5

git clone --depth 1 https://github.com/novomesk/qt-jpegxl-image-plugin.git
cd qt-jpegxl-image-plugin.git
git clone --depth 1 https://github.com/libjxl/libjxl.git --recursive
cd libjxl
mkdir build
cd build
cmake -G "MSYS Makefiles" -DCMAKE_INSTALL_PREFIX=/mingw64 -DCMAKE_BUILD_TYPE=Release -DJPEGXL_ENABLE_PLUGINS=OFF -DBUILD_TESTING=OFF -DJPEGXL_WARNINGS_AS_ERRORS=OFF -DJPEGXL_ENABLE_SJPEG=OFF -DJPEGXL_ENABLE_BENCHMARK=OFF -DJPEGXL_ENABLE_EXAMPLES=OFF -DJPEGXL_ENABLE_MANPAGES=OFF -DJPEGXL_FORCE_SYSTEM_BROTLI=ON -DCMAKE_CXX_FLAGS="-DHWY_COMPILE_ONLY_SCALAR" ..
make -j4
make install
cd ../..
./build_libqjpegxl_dynamic.sh

Plugin name will be qjpegxl.dll and it needs libjxl.dll, libjxl_threads.dll, libbrotlicommon.dll, libbrotlidec.dll, libbrotlienc.dll

I had problems with crash on MSYS2 too, that's why I use the -DHWY_COMPILE_ONLY_SCALAR workaround to avoid AVX2 functionality.

Here is the plug-in with qimgv: http://188.121.162.14/qimgv/qimgv_2021-06-14.zip

eddiezato commented 3 years ago

Ok. I managed to build qimgv, qavif and qjpegxl myself. So this issue is solved at least for me. 😉

eddiezato commented 3 years ago

Is there an easy way to automatically detect all the dependent dlls needed for qimgv to work properly?

easymodo commented 3 years ago

i use depwalker but there is probably a better alternative

(and windeployqt ofcourse)

easymodo commented 3 years ago

@novomesk thanks, the thing is working! it was probably one of those compile flags for libjxl

novomesk commented 3 years ago

Avif maybe, unless it requires alot of heavy dll's. In that case i'll provide an optional package with image plugins.

@easymodo I observed that qimgv v0.9.2 alpha2 for Windows was made using Qt 5.12.4

I recommend to upgrade to Qt 5.15 in future release because some of my plug-ins needs at least Qt 5.14

Of course I can build qimgv by myself but people prefer to use official builds made by the software author.

easymodo commented 3 years ago

i already have everything built with 5.15 just fixing some small stuff before release

novomesk commented 3 years ago

FYI: MSYS2 package called mingw-w64-kimageformats-qt5 5.85.0-2 will be updated hopefully in the near future to contain AVIF and HEIF plug-ins. The kimg_avif.dll is very similar to my qt-avif-image-plugin but the kimg_heif.dll is different to the traditional qt-heif-image-plugin.

Regarding JXL: MSYS2 now have mingw-w64-highway package. It could be used to build the libjxl library with -DJPEGXL_FORCE_SYSTEM_HWY=ON parameter.

You know there were some crashes in the past caused by the old bundled highway/HWY library. I used the -DCMAKE_CXX_FLAGS="-DHWY_COMPILE_ONLY_SCALAR" workaround previously but it came with performance penalty (AVX2 was disabled).

According developers using the new highway 0.14.2 should resolve MSYS2 crashes (I haven't tested yet on MSYS2).

novomesk commented 3 years ago

@eddiezato Can you please test if you will be able to play following animation in your qimgv Windows build?

http://188.121.162.14/jxl/animation.avif

http://188.121.162.14/jxl/animation.jxl

Is there any difference on your side between running qimgv.exe inside MSYS2 environment directly or running it from Windows (other location with copied DLL files)?

eddiezato commented 3 years ago

@novomesk Avif plays very sluggishly. Jxl is good, but it takes more than 20 seconds to run qimgv, at least on my PC.

In msys2 environment qimgv doesn't play the jxl animation. If copy all the dependencies next to the exe, it runs without any difference from running outside of msys2.

easymodo commented 3 years ago

Same on arch ('qt5-jpegxl-image-plugin-git', 'qt-avif-image-plugin-git'). I'm using QMovie to read animation files.

The issue with avif is that its pretty slow - QMovie::jumpToNextFrame() takes ~70ms

JXL has a different problem - it fully loads all frames in memory when you call QMovie::jumpToFrame(0). With your file it takes lots of time & a few gigs of ram

eddiezato commented 3 years ago

In msys2 environment qimgv doesn't play the jxl animation.

Nevermind, it's because of missing mime\packages\image-jxl.xml

novomesk commented 3 years ago

Thanks for testing. I have few observations/comments.

@easymodo When I put animation.avif and animation.jxl into one folder and start qimgv animation.avif, qimgv plays the AVIF but opens the JXL file in the background. I see my debug messages from qt-jpegxl-image-plugin during AVIF playback.

So this parallel decoding of two files is one reason of the slowdown.

The JXL animation is indeed very resource-hungry, JXL plug-in loads everything to memory first.

Right now Google Chrome or MS Edge have problem to play the animation.jxl too.

I will probably re-design the qt-jpegxl-image-plugin to avoid very high memory usage.

It is not a typical JXL animation, it is an extreme corner case I made just for testing.

@eddiezato When I look at your script https://github.com/eddiezato/builds/blob/main/avif.sh I see that you build libavif with AOM support only. I did that in the past too. It is OK for static AVIF and for simple animations. I suggest to add new dav1d decoder which is significantly faster to decode especially for 8 bit images. To build libavif with libyuv may accelerate decoding even further. Very few people build libavif with libyuv.

Google Chrome can play animation.avif fluently even on my mobile phone. I will keep investigating where are the bottlenecks.

easymodo commented 3 years ago

@novomesk

I will probably re-design the qt-jpegxl-image-plugin to avoid very high memory usage

Yeah just mimic the behavior of avif plugin (decode frames ondemand)

eddiezato commented 3 years ago

@novomesk I previously built libavif with dav1d and compared the decoding speed with aom. For static images there isn't much difference, especially with the latest improvements of aom. And personally I'm not a fan of animated images, I prefer to use video formats for such cases. But I'll give it a try. How can I get the avif plugin to prefer dav1d decoder by default?

novomesk commented 3 years ago

dav1d is preferred decoder by libavif when it is available. It is enough to rebuild libavif with dav1d support. AVIF plug-in let libavif to choose the decoder.

eddiezato commented 3 years ago

Ok, I updated my script. It now builds with aom, dav1d and libyuv. Playing animation.avif became slightly better, but still slower than it should be.

easymodo commented 3 years ago

I'm blocking animated jxl as the plugin is not quite there yet. Just to avoid someone locking up their system with a random file. You can turn it back on at settings -> advanced

eddiezato commented 3 years ago

I'm thinking of building libavif/qavif without aom, just dav1d and libyuv. I use qimgv only for viewing images and personally don't need to save files. This gives 5-times less size of libavif.dll as a result.

upd: but this breaks Crop & Save, of course. 😜

novomesk commented 3 years ago

@eddiezato Yes, you can build libavif without encoders if you need only reading capability. Author of qView did that because his app is viewer only (no save function). Also KaOS distribution has libavif with dav1d only.

easymodo commented 3 years ago

----> Version 1.0.0

Both jxl and avif plugins are included

novomesk commented 3 years ago

I think the archive is missing some DLLs:

libmng-2.dll needed by imageformats/qmng.dll libtiff-5.dll needed by imageformats/qtiff.dll libwebp-7.dll needed by imageformats/qwebp.dll libwebpdemux-2.dll libwebpmux-3.dll

easymodo commented 3 years ago

Oh crap. Thanks for catching this early.

Reuploaded, lets pretend this didnt happen.

novomesk commented 3 years ago

I have new plug-ins. AVIF is much faster now especially when libavif is built with libyuv. JPEG XL plug-in uses less memory, decodes frames on-demand. There is also new release of libjxl 0.6

eddiezato commented 3 years ago

Is there any advantage to building (on windows) qimgv and qjxl/qavif with qt 6.2.0 instead of qt 5.15.2?

novomesk commented 3 years ago

I think regarding the plug-ins, there is no significant difference, yet. In the future, I will use some Qt6 features.

eddiezato commented 3 years ago

Maybe it's just my imagination, but qt6 makes qimgv seem a little bit faster. 😜

eddiezato commented 2 years ago

@easymodo @novomesk Sorry for ping, can you help investigate the problem?

Built the latest libjxl. Built the latest qimgv with Qt 6.2.1. Built the latest qt-jpegxl-image-plugin with Qt 6.2.1. Took the image sample_5184×3456.jpeg from here. Encoded the image with settings: cjxl -j -d 0.5 -e 8 (must be -d ≤ 0.9 and -e ≥ 8). Try to open the .jxl - qimgv doesn't show anything.

If build not the latest version of libjxl but v0.6.1 and then build qt-jpegxl-image-plugin on that version, qimgv will show the image.

All builds with msys2/mingw64.

eddiezato commented 2 years ago

It looks like a libjxl bug. Sorry again.

PS > cjxl 0.jpg 1.jxl -j -d 0.5 -e 8
JPEG XL encoder v0.7.0 10f5c38 [SSE4]
Read 5184x3456 image, 31.5 MP/s
Encoding [VarDCT, d0.500, kitten], 4 threads.
Compressed to 5494140 bytes (2.453 bpp).
5184 x 3456, 0.52 MP/s [0.52, 0.52], 1 reps, 4 threads.
PS > djxl 1.jxl 2.png
JPEG XL decoder v0.7.0 10f5c38 [SSE4]
Read 5494140 compressed bytes.
Failed to decompress to pixels.
eddiezato commented 2 years ago

Playing around with msys2, I tried to build qimgv in msys2/clang64 environment with Qt v6.3.0. Everything works flawlessly, except that qimgv can't load files with Cyrillic names (I think it's the same with other Unicode paths). I got this problem with exiv2 as well, I created the issue. But f.e. cjxl, cwebp, jpegtran built in the same environment have no problem with Unicode paths.

easymodo commented 2 years ago

@eddiezato Idk, works with msys2 + mingw.. Might try clang later

qt 6.3.0... Everything works flawlessly

By the way does that include videoplayer? I just cant make it work with 6.x (getting no opengl support set errors)

eddiezato commented 2 years ago

does that include videoplayer

Sorry, I build without mpv support, so no help here.

works with msys2 + mingw

Yep, it works fine. But since I build everything with clang anyway, I decided to try not to mix the libs created with different compilers. So I set up the msys2/clang64 environment and build apps in it. The build process is the same, except that the dependencies must be mingw-w64-clang-x86_64-*, but C/C++ libraries are different in this environment, maybe that's the case. At the same time, apps other than exiv2 and qimgv, have no problem with Unicode paths, such as flac or yacreader.

My build script, if anyone is interested:

export CC=clang CXX=clang++
CFL='-ffunction-sections -fdata-sections -march=native -mtune=native -O3 -pipe'
LDFL='-Wl,--gc-sections'
MGNT='\e[1;35m'
RST='\e[0m'

rm -rf qimgv
printf "\n${MGNT}:: Prepare qimgv ::${RST}\n"
git clone --depth 1 https://github.com/easymodo/qimgv.git
cd qimgv

printf "\n${MGNT}:: Build exiv2 ::${RST}\n"
git clone --branch 0.27-nightly --depth 1 https://github.com/Exiv2/exiv2.git
cd exiv2
cmake -B build -G Ninja -S ./ \
    -DCMAKE_INSTALL_PREFIX='../ext' \
    -DCMAKE_BUILD_TYPE=Release \
    -DEXIV2_ENABLE_WIN_UNICODE=ON \
    -DEXIV2_ENABLE_BMFF=ON \
    -DEXIV2_BUILD_SAMPLES=OFF \
    -DCMAKE_C_FLAGS="$CFL" -DCMAKE_CXX_FLAGS="$CFL -pthread" -DCMAKE_EXE_LINKER_FLAGS="$LDFL"
ninja install -C build
cd ..

printf "\n${MGNT}:: Build opencv ::${RST}\n"
git clone --depth 1 --branch 4.5.5 https://github.com/opencv/opencv.git
cd opencv
cmake -B build -G Ninja -S ./ \
    -DCMAKE_INSTALL_PREFIX='../ext' \
    -DCMAKE_BUILD_TYPE=Release \
    -DBUILD_LIST='core,imgproc' \
    -DWITH_1394=OFF \
    -DWITH_VTK=OFF \
    -DWITH_FFMPEG=OFF \
    -DWITH_GSTREAMER=OFF \
    -DWITH_DSHOW=OFF \
    -DWITH_QUIRC=OFF \
    -DBUILD_SHARED_LIBS=ON \
    -DCMAKE_C_FLAGS="$CFL" -DCMAKE_CXX_FLAGS="$CFL" -DCMAKE_EXE_LINKER_FLAGS="$LDFL"
ninja install -C build
cd ..

printf "\n${MGNT}:: Build qimgv ::${RST}\n"
sed -i 's|opencv4/||' qimgv/3rdparty/QtOpenCV/cvmatandqimage.{h,cpp}
cmake -B build -G Ninja -S ./ \
    -DCMAKE_BUILD_TYPE=Release \
    -DVIDEO_SUPPORT=OFF \
    -DOPENCV_SUPPORT=ON \
    -DEXIV2=ON \
    -DCMAKE_PREFIX_PATH=$(realpath 'ext') \
    -DCMAKE_C_FLAGS="$CFL" -DCMAKE_CXX_FLAGS="$CFL" -DCMAKE_EXE_LINKER_FLAGS="$LDFL"
ninja -C build
eddiezato commented 2 years ago

I opened a discussion in the msys2/mingw repo. The problem with unicode seems to be in libc++. qimgv built in msys2/ucrt64 environment (libstdc++) works fine.

However, it can't be said that qimgv with libc++ absolutely unable to open an image with unicode path. It can, but in this way:

At the same time QuickViewer, f.e., which has been frozen in development for some time, has no problems with unicode paths, even when compiled against libc++.

novomesk commented 2 years ago

@easymodo Do you remember that we used -DCMAKE_CXX_FLAGS="-DHWY_COMPILE_ONLY_SCALAR" to avoid libjxl crashing on MSYS2?

I built libjxl on MSYS2 recently and I was unable to reproduce the crash again. I don't know if the problem was solved by newer gcc in MSYS2 or by libjxl or it is just a co-incidence.

When you have time, can you try to remove the flag so see if you get the crashes or not?

easymodo commented 2 years ago

@novomesk

When you have time, can you try to remove the flag so see if you get the crashes or not?

Tried two builds with and without the flag, works in both cases.