Adding an image to your JUCE application [SOLVED]

I wanted to incorporate an image into my component. (Eventually I want to play an animated GIF, but baby steps first!). So I peruse the documentation, and this is the best I came up with:

first create a default constructed Image gifImage; in the private: section as this will store an invalid Image for us on the stack, ready for us when we load it up with something:

Then we need a File object to store the path to the file. Initially I tried File file{“test.gif”} And even though the documentation says: "If the path supplied is a relative path, it is taken to be relative to the current working directory" It gives me an assertion error. The JUCE forums revealed this bit of code that seems to work (without assertion failure):

File file = File::getCurrentWorkingDirectory().getChildFile("test.gif");


Side question: What is File:: doing? Is it constructing a disposable object (with no name) so that we can access it’s getCurrentWorkingDirectory() function one time only? rather than having to do this:

File file;
File file2;
file2 = file.getWorkingDirectory();
file3 = file2.getChildFile("test.gif");

Also can anyone name what is happening when a function has a . to another function, so I can learn more about this syntax?


Anyway, so now I have a file loaded into file, I need to make an InputStream because that’s what GIFImageFormat is going to want to return an Image. So…

FileInputStream fileInputStream(file);

No errors yet.

Now it’s only when I’m on the last stage that it results in the assertion error: JUCE Assertion failure in juce_FileInputStream.cpp:46:

GIFImageFormat gifImageFormat;
gifImage = gifImageFormat.decodeImage(fileInputStream);
// Hooray we have loaded a file into gifImage!

Side question: shouldn’t I be able to do something like this, just as before?

gifImage = GIFImageFormat::decodeImage(fileInputStream);

So this is where I am, unable to load up an image from file :frowning:

Sorry for the tedious, perhaps constant, and uninteresting questions I keep asking. I really am trying to figure this out on my own, and have dedicated about two hours to this problem already.

Kind of Side Question: If anyone has any recommendation for what skill I am lacking, outside of this particular problem, that is going to help me with future such problems (i.e. reading / interpreting documentation etc.) - what fundamental programming skill I am missing and where I can go to get better, then please say!

As always, a million thanks

1 Like

Why not just use ImageFileFormat::loadFrom with the overload that takes in File?

Image myimage = ImageFileFormat::loadFrom(File("thefullpathtothefile.gif"));
1 Like

Checkout ImageCache, it has a method for getting from a file

Thanks @Xenakios, @richie,

I have tried both methods:

Image gifImage = ImageFileFormat::loadFrom(File::getCurrentWorkingDirectory().getChildFile("test2.gif"));

and

Image gifImage = ImageCache::getFromFile(File::getCurrentWorkingDirectory().getChildFile("test2.gif"));

on multiple gif files. Neither prints an error to the console! :slight_smile: but neither are displaying either. (just blank/black)

I’m using g.drawImageAt(gifImage, 0, 0, false); inside my paint function, and setSize() is set to bigger than the size of the gifs.

Incidentally, both of you have triggered my side question regarding the use of the scope resolution operator :: I can’t figure out what it’s doing in these cases.

Maybe the gif file is in the wrong location?

I’m assuming the working directory is wherever the the source files are contained, like how #include works. so for example, i put test.gif in the same folder that has MainComponent.h (i don’t have a MainComponent.cpp)

Don’t use the working directory, it can be whatever, depending on things. You can use an absolute path while testing and for production use you can use some other suitable location you would form dynamically during runtime. (For example by using File’s getSpecialLocation method.)

In these cases it’s for calling a static method of a class. (Method that doesn’t need a separate object instance.)

Awesome, using the absolute path fixed it. Thanks as always! But what if I want to bundle the images as part of the executable binary? I know htere’s something I can do with the Projucer to import existing files. But then how do I reference it?

Nice! Thanks for that

drop the files into Projucer and they should automatically be marked as “Binary Resource”.

To access them:

Image myImage = ImageFileFormat::loadFrom(BinaryData::the_image_file_png, BinaryData::the_image_file_pngSize);

There is a limit of 20mb for BinaryData, if for some reason you really need to exceed that then there is BinaryBuilder that is included in the extras of JUCE, I forget if it comes pre-built or if you need to build it yourself, but I would imagine there is a fairly decent reason for that 20mb limit and you would probably be better off loading large assets from disk and have your installer place the files in a known location.

4 Likes

Thank you richie!

Btw, How do you come to know this kind of stuff? I feel like using the forum for every little thing I want to do is rather parasitic of everyone’s time. I know the docs are probably where it’s at, but I just don’t seem to know how to extract and put together the relevant information.

I know it sounds dumb, but there are plenty of programming tutorials, but is there maybe a " how to reading the docs (RTFM)" tutorial, or something?

Or do you just come to know this because JUCE uses only industry standard principles, and you just happened to learn them elsewhere?

Could someone give an example please?
What are “the_image_file_png” and “the_image_file_pngSize”?

From my side, I added the image as a resource in the projucer.
As I work on Xcode, I checked in the projucer:

  • binary resource
  • Xcode resource

(I don’t know if both are necessary.)

So I can see in the projucer that the image has a name and a size.
What are the next steps if I want to use the above quote?

Ok, I’ve got it:
the_image_file_png: the name of the image with the extension “.png” replaced by “_png”.
the_image_file_pngSize: the name of the image with the extension “.png” replaced by “_pngSize”.

About my previous question, do I need to check binary resource as well as Xcode resource?

(And also… a tuto on loading images would be great! :wink:

The Xcode resource will copy the file into the created bundle/Resources while the binary resource creates a machine code blob that is embedded in the binary.

Advantage of binary data is, it is portable for osx, windows and linux, disadvantage is, there is a file size limit for the binary.

Thanks.
So is it good tho check both for an audioplugin build with Xcode?

No, you only need Binary resource for images. The Xcode resource is not portable (windows doesn’t have this concept).
And unless you open that image as file, you don’t need the xcode resource.
For images it is best to tick only binary resource and load the image with

auto image = juce::ImageCache::getFromMemory (BinaryData::file_png, BinaryData::file_pngSize);