Recent

Author Topic: Question: Handling large image files  (Read 2745 times)

Timur Born

  • New Member
  • *
  • Posts: 16
Question: Handling large image files
« on: December 19, 2020, 05:22:17 pm »
Ahoi.

I am currently testing Lazarus vs. QT vs. whatever to decide which would be suitable to code an image viewer that launches fast, is able to load several large images for comparison and runs multi-threaded for all kinds of operations. GUI and processing back-end should be separated (and maybe even in different languages/processes) so that one stays reactive when the other is busy.

Since I would have to start from scratch learning the language(s) and IDEs I am doing preliminary checks and test on what is already offered. First I compared memory consumption of simple empty windows that Larazus/QT/VS start with when a new project is created in order to get an idea of launch times/resource-usage. Lazarus and QT both do well in this, even though VS C++ MFC was even smaller, .NET WinForms was unsurprisingly larger and WPF came surprisingly last by quite a gap.

For comparison of what each platform offers for image viewieng I downloaded several Lazarus/Pascal and QT based image-viewers and opened a 3 GB large uncompressed TIFF image. Furthermore I used this old example code for Lazarus to open and display an image (changed FileExistsUTF8 to FileExists to make it work):

https://lazplanet.blogspot.com/2013/05/a-simple-image-viewer-from-start-to.html

Unfortunately I was not able to open and display the test image via this code or the Lazarus based image viewers I could find. So any hints on where to start would be appreciated. I would also like to read shared experience on how well Lazarus is suited to handle this kind of coding challenge?!

PS: It's noteworthy that my favorite image viewer Faststone Image Viewer is said to be written in Delphi, but it's unfortunately stuck in 32-bit. I know/use/tested a lot of different commercial and free image viewers over the years and thus generally know their strengths and weaknesses.
« Last Edit: December 19, 2020, 05:34:01 pm by Timur Born »

Handoko

  • Hero Member
  • *****
  • Posts: 4139
  • My goal: build my own game engine using Lazarus
Re: Question: Handling large image files
« Reply #1 on: December 19, 2020, 07:48:25 pm »
Hello Timur Born,
Welcome to the forum.

Unfortunately I was not able to open and display the test image ...

This simple demo shows how to load and show an image using Lazarus, try it:
https://forum.lazarus.freepascal.org/index.php/topic,37442.msg251587.html#msg251587

Because you want to develop an image viewer program, I should tell you not all graphics formats are supported and it depends on which library you are using. For example 2 versions of glSlideshow but the file format support are different (FCL-Image vs BGRABitmap):
https://forum.lazarus.freepascal.org/index.php/topic,35313.msg258981.html#msg258981

And here is the list of supported graphics libraries:
https://wiki.lazarus.freepascal.org/Graphics_libraries

... able to load several large images ...

Maybe you will be interested to read this:
https://forum.lazarus.freepascal.org/index.php/topic,50444.msg368161.html#msg368161

lainz

  • Hero Member
  • *****
  • Posts: 3991
  • Leandro Diaz
Re: Question: Handling large image files
« Reply #2 on: December 19, 2020, 07:51:21 pm »
Have you tried LazPaint? Made by circular, is really fast.
https://lainz.github.io/ - My Website :)
https://lazpaint.github.io/ -  Download LazPaint

Timur Born

  • New Member
  • *
  • Posts: 16
Re: Question: Handling large image files
« Reply #3 on: December 19, 2020, 08:56:08 pm »
Have you tried LazPaint? Made by circular, is really fast.
Thanks for the hint. I already tried LazPaint and LazView. It surprises me that LazPaint comes with its own file open dialog and said dialog already fails to open the image with a EOutofMemory error (TBGRAWinBitmap.RellocBitmap: Windows error 87).
« Last Edit: December 19, 2020, 09:18:13 pm by Timur Born »

Timur Born

  • New Member
  • *
  • Posts: 16
Re: Question: Handling large image files
« Reply #4 on: December 19, 2020, 09:10:49 pm »
Hello Timur Born,
Welcome to the forum.
Thanks for the warm welcome and the links, I will read through them.

One problem with image format files is that they seemingly cannot be decoded multi-threaded. I remember that I saw one viewer (maybe ACDSee) using two threads to decode the TIFF files, but overall it's one thread per image (JPEG, PNG, TIFF). This also is a bottleneck for modern PDF viewers when PDF files are image heavy.

After reading a bit in the last link provided it maybe makes sense to write the front-end (GUI) part in Lazarus and do the backend in C/C++. Currently I am only musing about possibilities.

It is worth mentioning that the QT based Nomacs viewer is very fast at viewing these large files, maybe even faster than anything I tried yet. Even only using a single-thread opens the displays the 3 gb TIFF file within 3 seconds and then all scrolling/zooming is smooth (contrary to XnViewMP or Ifranview). Memory consumption quite high, though (7.5 gb private after loading the 3 gb image).

Quote
This simple demo shows how to load and show an image using Lazarus, try it:
I am still trying to wrap my head around it. When I compile it as is then the window stays empty (no controls at all). Do I have to create the controls in the form editor and rename them according to the code? When I add controls it changes the code to fit in the new controls first.

« Last Edit: December 19, 2020, 09:23:49 pm by Timur Born »

circular

  • Hero Member
  • *****
  • Posts: 3677
    • Personal webpage
Re: Question: Handling large image files
« Reply #5 on: December 21, 2020, 08:21:55 am »
Have you tried LazPaint? Made by circular, is really fast.
Thanks for the hint. I already tried LazPaint and LazView. It surprises me that LazPaint comes with its own file open dialog and said dialog already fails to open the image with a EOutofMemory error (TBGRAWinBitmap.RellocBitmap: Windows error 87).
LazPaint is not made for images larger than 256 Mb. It would be interesting for me to know though when the problem happens and whether it is a crash or just an error message.
« Last Edit: December 21, 2020, 08:23:45 am by circular »
Conscience is the debugger of the mind

Timur Born

  • New Member
  • *
  • Posts: 16
Re: Question: Handling large image files
« Reply #6 on: December 21, 2020, 12:40:01 pm »
LazPaint is able to open a 1539 mb non standard uncompressed TIFF file and its more standard 1350 mb variant, but it takes 8 minutes to do so instead of 3-10 seconds. Loading the preview in the load dialog only takes seconds, though still is slower than loading the whole image in Nomacs (QT + OpenCV based).

LazPaint hits over 280 mio virtual memory pagefaults while loading the image (580 - 750k per second), while Nomacs finishes at only 1.7 mio. There also seem to be more pagefaults while scrolling around the zoomed image, but I did not test that thoroughly.

Scrolling in the zoomed image is smooth between 200 - 500%, but more juddery below 200% and above 500% (when the grid shows up).

There also is a visible "rolling shutter" effect skewing straight lines during left/right scrolling because of the image is build/refreshed from top to bottom.

The error with the 3 gb file happens when the preview is supposed to be created in the load dialog, it does not crash and another image can be chosen/opened afterwards.

Judging from this observations it seems that building the backend on top of OpenCV seems like a good idea, which in turn points more towards C++. There are some OpenCV Delphi/Lazarus ports, but they don't seem to be actively maintained!?

Using a C++ backend in combination with a Lazarus UI might be viable, but I don't know how well this could be integrated (maybe even using 2 processes via inter-process communication via shared memory)?!
« Last Edit: December 21, 2020, 01:57:36 pm by Timur Born »

winni

  • Hero Member
  • *****
  • Posts: 2274
Re: Question: Handling large image files
« Reply #7 on: December 21, 2020, 02:19:31 pm »
Hi!

The biggest TIFF file on my disks is 668 MB,  8192 x4096 Pixel, RGB

The file loading takes 3..4 seconds
Resizing down and up happes in realtime
Moving  the image happes in realtime

One message while loading the image:
Code: Text  [Select][+][-]
  1. [DEBUG] Name com.canonical.AppMenu.Registrar does not exist on the session bus
  2.  

Whatever Lazpaint wants to tell me.
No problems.

Winni

avra

  • Hero Member
  • *****
  • Posts: 2141
    • Additional info
Re: Question: Handling large image files
« Reply #8 on: December 21, 2020, 03:46:31 pm »
The error with the 3 gb file happens when the preview is supposed to be created in the load dialog, it does not crash and another image can be chosen/opened afterwards.
If image loader tries to load whole image into memory, then you should check if your compiled Lazarus application is 32-bit, or OS is 32-bit.

Have you looked into https://github.com/galfar/imaginglib ?
ct2laz - Conversion between Lazarus and CodeTyphon
bithelpers - Bit manipulation for standard types
pasettimino - Siemens S7 PLC lib

circular

  • Hero Member
  • *****
  • Posts: 3677
    • Personal webpage
Re: Question: Handling large image files
« Reply #9 on: December 21, 2020, 03:55:25 pm »
Thanks for the infos Timur.

The decompression algorithms are a bit slow I suppose. Not sure where this could be optimized.

About the pagefaults I am not really surprised because the image data is stored in rows in BGRABitmap and the TIFF may be provided as a grid of images. Not the same layout. There may be other reasons that I am unaware of.

Another limitation is that images in LazPaint are reduced to fit a 8192x8192 maximum dimension. The long time when loading is probably due to this resampling (done with high quality).

So, all of this seems normal to me given the current implementation. Indeed you need another library for those big images.

Code: [Select]
[DEBUG] Name com.canonical.AppMenu.Registrar does not exist on the session busMaybe LCL trying to get a service on a Linux system.
Conscience is the debugger of the mind

Timur Born

  • New Member
  • *
  • Posts: 16
Re: Question: Handling large image files
« Reply #10 on: December 21, 2020, 05:51:41 pm »
Using 64 bit LazPaint + 64 W10 here. Images were uncompressed TIFF, but between 25200 and 32000 px on the long side. One could implement the image handling from scratch, but seeing how well Nomacs does on the performance front makes looking at OpenCV more tempting.

Nomacs fails mostly on the UI front, while my favorite FastStone Image Viewer fails at 64-bit (and the author not even answering mails from license owners).

Lazarus is very tempting to build a GUI app with, both being convenient and compiled native code. But having to reinvent the wheel for the backend while (C++ based) solutions are already out there is a big problem.

circular

  • Hero Member
  • *****
  • Posts: 3677
    • Personal webpage
Re: Question: Handling large image files
« Reply #11 on: December 21, 2020, 07:45:46 pm »
That's understandable. You can use C++ libraries in FreePascal though.
Conscience is the debugger of the mind

Timur Born

  • New Member
  • *
  • Posts: 16
Re: Question: Handling large image files
« Reply #12 on: December 21, 2020, 08:07:06 pm »
I speculated as much. How easy or convoluted would that be? Can these be statically linked, too?

circular

  • Hero Member
  • *****
  • Posts: 3677
    • Personal webpage
Re: Question: Handling large image files
« Reply #13 on: December 21, 2020, 09:03:58 pm »
In all cases, you need a "header" file, so a Pascal unit that defines the procedures (with cdecl keyword for C) and types.

It is possible to point directly to a library using the external keyword. That's the simple but I guess you can do that only if you are sure the library will be available. Otherwise it is also possible to statically link an object file (I never tried it personally). Here is the doc on external:
https://www.freepascal.org/docs-html/current/prog/progsu150.html

You can have more control over the dependency to the library. You need for this code that loads the library and retrieve the pointers to the procedures. Here is such file for example for WebP library: https://github.com/bgrabitmap/bgrabitmap/blob/master/bgrabitmap/libwebp.pas. That's more stuff to write because in this case you define variables that will contain the procedures and the code that actually loads the library. On the other hand, you can choose when to load/unload the library, do something else if the library is not present, etc.
Conscience is the debugger of the mind

Timur Born

  • New Member
  • *
  • Posts: 16
Re: Question: Handling large image files
« Reply #14 on: December 22, 2020, 01:06:44 am »
Have you looked into https://github.com/galfar/imaginglib ?
Sorry, I missed this part. But yes, I already looked into its compiled demos and tried LCL Imager. It does not support TIFF, so I had it open a PNG version of the 1.35 gb image. It is faster that LazPaint, but still far too slow in opening the preview and image.

 

TinyPortal © 2005-2018