3

I want to make an application using Delphi. The problem is I am going to have a lot of TImage components in it - which will make the exe size extremely large. So far my exe is 20MB large and I have only completed the home page, by my calculations the exe alone will be more than 10GB in size - which is way too much.

How can I make an app with hundreds/thousands of images and yet let the exe be small in size?

mghie
  • 32,028
  • 6
  • 87
  • 129
Shaun Roselt
  • 1,650
  • 5
  • 18
  • 44

3 Answers3

11

Don't put the images in the executable. Keep them in external files and load them at runtime.

This will require you to stop loading the images into the TImage controls at design-time and instead use dynamic code to load the image, and transfer to the TImage control. There are many advantages of doing so:

  1. You keep your executable down to a reasonable size, one that can fit in the virtual address space.
  2. You can use the most appropriate compression format for the images. If I recall correctly, a Delphi TImage will persists to a .dfm file in a very inefficient way. You can choose to use PNG or JPEG compression.
  3. Keeping the files external allows you to better managed them when developing. You can keep them as separate files in your revision control system. Storing images in .dfm files makes for painstaking updates when you need to change the images. You have to do lots of interaction with the IDE. Storing as files allows you to overwrite the file, and commit to the repository.
David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
  • It could be useful to keep image files inside of EXE as binary resources. Then size of EXE will be reasonable (because of compressed image format) and deployment simple (because it is still 1 file). Simple example is here http://stackoverflow.com/questions/1153394/how-do-i-make-a-png-resource – Andrei Galatyn Jul 07 '14 at 13:08
  • @AndreiGalatyn That's true. However, if the images would be 10GB in a .dfm, no matter how you compress them I think you will have too large an executable – David Heffernan Jul 07 '14 at 13:10
  • I didn't suggest to use DFM, separate files can be directly compiled as binary resources into EXE (as i understand). And i supposed that resources from EXE will not be loaded into memory until you do it explicitly. – Andrei Galatyn Jul 07 '14 at 13:17
  • @AndreiGalatyn I know what you suggested. It's just that if it's going to be 10GB in .dfm files, it will still be, say 3-4GB as linked resources. The issue is not that all the memory is committed, but that the address space is reserved. You try and execute a 2GB exe file under 32 bit. The system won't be able to reserve 2GB contiguous address space. – David Heffernan Jul 07 '14 at 13:22
  • 1
    ... and everything included in the .dfm would let the IDE probably become very slow, also compile time being huge. And incremental updates of the exe would benefit from external images. +1 – Arnaud Bouchez Jul 07 '14 at 13:37
  • 1
    @David Do you sure that system will try to reserve address space for whole EXE-file including binary resources? I supposed it will not load (reserve address space etc) for resources inside of EXE. – Andrei Galatyn Jul 07 '14 at 13:40
  • @AndreiGalatyn Yes I am quite sure. If it doesn't reserve the address space, then there's no guarantee that it will be available. – David Heffernan Jul 07 '14 at 13:40
  • @David XE6 failed to compile project from IDE with 1GB file attached as resource (returns internal error). I have to agree that it is not good idea to keep big files inside of EXE. – Andrei Galatyn Jul 07 '14 at 13:57
  • 2
    Also, if the same image is used multiple times, then only one copy of that image is needed, then loaded into whichever image controls are needed. – Jerry Dodge Jul 07 '14 at 22:13
  • Thanks, but how do I do this? I do not know how to load it from startup and i have re calculated, it will be 100GB if im not mistaken, this is a lot of images, I am talking about thousands and thousands of images. – Shaun Roselt Jul 10 '14 at 12:22
  • Load the images from file, and then assign them to the image's Picture property. – David Heffernan Jul 10 '14 at 12:24
  • `Image1.Picture.Assign(Graphic)`. Where `Graphic` is a `TGraphic` descendent. Perhaps `TPngImage`. Or `TJpegImage`. The graphic would have been loaded with `Graphic.LoadFromFile(FileName)`. – David Heffernan Jul 10 '14 at 13:57
2

If you don't need to keep your images in their original size, you can read them in at program startup and scale them to their "working" size. This will reduce your memory requirements immensely - for example, reducing an image to half its original width and height reduces memory requirements to a quarter of the original image.

If the images don't change, you can do this offline in a separate build process and reduce the load time a lot too. Otherwise, you can cache the reduced images during the load process to speed it up the next time the program is started.

Pat Heuvel
  • 96
  • 4
  • *If you don't need to keep your images in their original size* is a pretty big if. Scaling down, then scaling back up results in a loss of quality. – David Heffernan Jul 08 '14 at 05:24
  • You're right, it's a big if - sorry I wasn't clearer. The OP hasn't told us how he intends to use the images. If they are simply to be shown in the application, they can be scaled down to a "display" size (say 150x100 for a nice round number) for a great saving in memory requirement as compared to an image off a camera at, say, 3000x2000. If the images need to be presentable in their original size, then my second suggestion (caching the reduced images) would be a way to go, as long as there is a method to relate the cached image to its original. – Pat Heuvel Jul 08 '14 at 06:39
  • You do need to recognise the issue of quality though which you seem to be neglecting. – David Heffernan Jul 08 '14 at 06:44
  • Again, the OP hasn't told us the intention wrt the images. Assuming you are referring to the quality of the images, this is dependent upon the nature of the OP's original problem. If he wishes simply to display the images as thumbnails, quality of those images will always suffer as you reduce a full-sized image to a thumbnail. My caching approach will permit him to produce (and maintain) the thumbnails without having to destroy the originals. As long as you can relate the cached images to the originals (and can therefore display them in full quality), where is the loss of quality? – Pat Heuvel Jul 09 '14 at 04:16
  • Sorry, David, I wasn't suggesting to scale down then scale back up. You're quite right, that would really be counterproductive. My intended approach is to create thumbnails which would be more resource-economical than full-quality images when displayed in bulk; then utilising the full-quality images as and when needed. – Pat Heuvel Jul 09 '14 at 04:25
  • So how does storing extra images, as well as the originals, help reduce the storage requirements? – David Heffernan Jul 09 '14 at 06:13
  • It doesn't reduce the storage requirements, but, combined with removing the images from the source, should significantly reduce the exe size (from the original question). – Pat Heuvel Jul 09 '14 at 06:28
  • Your answer doesn't talk about removing anything from the exe. But never mind. I was trying to ascertain how your answer was going to help with the question of storage. – David Heffernan Jul 09 '14 at 06:30
  • I assumed that if one loads the images at run time that one would not be compiling those same images into the binary. But we all know what happens when one assumes :) The OP said his problem was that the exe would be extremely large - removing the requirement for the images to be built into the binary would make the size of the binary more reasonable. Removing images from binary: storage: no improvement (those 10GB of images still have to go somewhere); binary: major improvement. So again, I apologise for not being clearer. – Pat Heuvel Jul 09 '14 at 06:55
1

You might find the binary code includes all the images as PNG file format, so it will be compile extremely application size for you.

I use the images in runtime, as JPG, so in the form's OnCreate events you can load from the Package.

Use the "Project" Menu "Deployment" to include your JPG files to the APK.

You can read more here: http://blogs.embarcadero.com/davidi/2013/11/23/43005/

Matt
  • 74,352
  • 26
  • 153
  • 180
ZsoZsoSoft
  • 11
  • 1