SDL embed image inside program executable - c++

Is it possible to embed an image within a program using SDL which can be used at run time.
For example, I have a program which brings up a splash screen on startup containing the logo and copyright information. Rather than having this image in a bitmap file and using SDL_LoadBMP to load it to a SDL_Surface. I would like to have the image embedded in the program binary, to stop someone potentially changing the splash image and copyright name.
Does anyone have any suggestions on ways to do this? Example code would be great.

Embedding a file in an executable is easy but there are some gotchas, there are several ways to do it including some portable and non-portable ways.
Using #embed
This will reportedly be part of C23. It may be on track to appear in C++26 as well. Check whether your compiler supports this feature. In the future, this may be the most portable and straightforward way to embed binary data.
static const unsigned char IMAGE_DATA[] = {
#embed "myimage.bmp
};
See WG14 n2592 for the feature proposal.
Advantages: simplest, easiest
Disadvantages: your compiler probably doesn’t support this yet
Convert the image to C code
Write a script to convert the image to a constant array in C. The script would look something like this in Python:
#!/usr/bin/env python3
print("static const unsigned char IMAGE_DATA[] = {{{}}};".format(
",".join(str(b) for b in open("myimage.bmp", "rb").read())))
Just pipe the output to a *.h file and include that file from one other file. You can get the size of the file with sizeof(IMAGE_DATA).
Advantages: portable
Disadvantages: requires Python to be installed, does not work if array is too large for compiler, requires adding a custom step to the build system
Convert the image to an object file
This is more platform-dependent. On platforms with GNU binutils toolchains (e.g. Linux) you can use objcopy, I think bin2obj works on Microsoft toolchains.
Advantages: works everywhere
Disadvantages: non-portable, requires adding a custom step to the build system, the custom step might be tricky to get right
On GNU binutils toolchains, with objcopy
The objcopy program lets you specify binary as the input format, but then you need to specify the architecture explicitly... so you will have to modify the command for i386 and x64 versions of your executable.
$ objcopy --input binary --output elf32-i386 --binary-architecture i386 \
myimage.bmp myimage.o
You can get the data from C by using the following declarations:
// Ignore the fact that these are char...
extern char _binary_myimage_bmp_start, _binary_myimage_bmp_end;
#define MYIMAGE_DATA ((void *) &_binary_myimage_bmp_start)
#define MYIMAGE_SIZE \
((size_t) (&_binary_myimage_bmp_end - &_binary_myimage_bmp_start))
Use an assembler directive
Paradoxically, embedding a static file is fairly easy in assembler. Assemblers often have directives like .incbin (which works with GAS and YASM).
Advantages: works everywhere
Disadvantages: non-portable, assembler syntax is different between platforms
(Windows) Embed the file as a resource
On Windows, you can embed resources in an EXE and then get the resources using library calls.
Advantages: probably easiest if you are on Windows
Disadvantages: only works on Windows

You can export the image as .xpm format (in gimp) and include it to your code. But you will need SDL_Image.h to load it as SDL_Surface.
As it is in this doc, is really simple:
//To create a surface from an XPM image included in C source, use:
SDL_Surface *IMG_ReadXPMFromArray(char **xpm);
A example in C/C++:
#include <SDL/SDL.h>
#include "test.xpm"
#include <SDL/SDL_image.h>
SDL_Surface *image;
SDL_Surface *screen;
int main(int argc, char **argv)
{
SDL_Init(SDL_INIT_EVERYTHING);
screen = SDL_SetVideoMode(800,600,32,SDL_SWSURFACE);
image = IMG_ReadXPMFromArray(test_xpm); //the .xpm image is a char array. "test_xpm" is the name of the char array
SDL_Rect offset;
offset.x = 0;
offset.y = 0;
SDL_BlitSurface(image,NULL,screen,&offset);
SDL_Flip(screen);
SDL_Delay(5000);
return 0;
}
I hope this helps.

With gimp you can save a image as c code.

Related

How to embed font and other image files when using graphic libraries like SFML

Many of you have probably wondered- how can I get rid of a font or any other single file from the drive when using a library like SFML, which needs to load a font from a file path.
So, how do I embed that data into the executable, so the resulting executable does not depend on those resource files anymore?
First of all, we have to get our resource. I have downloaded "BalooBhaijaan-Regular.ttf" font from google fonts.
Then, one should get the binary data of the given font. The easiest way to achieve this in my opinion is to use the linux "xxd" command with -i parameter which outputs in a C-style array.
Let's redirect the output to a file because It is usually going to be long if we are talking about true type fonts or larger images:
xxd -i BalooBhaijaan-Regular.ttf > font_data.txt
Create an empty C/C++ header or put the font data into an already existing file. I prefer using new header files as the output is going to be really long.
Of course, after pasting into your IDE you can change the array type to const as the content of a font usually doesn't change.
This is how it looks in my IDE:
You might of course wonder why is this a char array - simply because in a char array each "field" represents one byte.
As you might have noticed, xxd also creates another variable for us - the last variable in the font_data.txt is an unsigned int which informs us about the length of the array. We will need this later. Name of the "length-informing" integer is same as name of the array with "_len" suffix
Now, there are two ways to proceed:
1. load font from the memory using a builtin method (some libraries support it, SFML does)
2. create a "fake" file and load it
Lets talk about both cases
1.
This one is fairly simple, sfml supports loading file from memory given it's address and size, so we can just do this:
#include "BalooBhaijaanFont.hpp"
#include <SFML/Graphics.hpp>
int main(int argc, char** argv) {
sf::RenderWindow mainWindow(sf::VideoMode(200,100), L"TEST");
sf::Font fromMem;
fromMem.loadFromMemory(&BalooBhaijaan_Regular_ttf, BalooBhaijaan_Regular_ttf_len);
sf::Text text("WORKS!", fromMem);
while(mainWindow.isOpen()){
mainWindow.draw(text);
mainWindow.display();
}
return 0;
}
As you can see, loading it with a builtin function is really easy.
2.
Now it's time for a temporary file approach which i really do NOT recommend - most libraries support loading from memory and if you are making your own library you are going to end with having a memory load function anyway.
Whilst it is still possible to create a file just to read it to a font class and then remove it, I do not see any sense of using this method unless you are extremely annoyed by additional files in your folders.
Just for reference:
#include "BalooBhaijaanFont.hpp"
#include <SFML/Graphics.hpp>
int main(int argc, char** argv) {
sf::RenderWindow mainWindow(sf::VideoMode(200,100), L"TEST");
sf::Font fromFile;
{
FILE * tempFile = fopen("tmpfont.ttf", "wb");
fwrite( BalooBhaijaan_Regular_ttf, sizeof(char), BalooBhaijaan_Regular_ttf_len, tempFile );
fclose(tempFile);
fromFile.loadFromFile("tmpfont.ttf");
std::remove("tmpfont.ttf");
}
sf::Text text("WORKS!", fromFile);
while(mainWindow.isOpen()){
mainWindow.draw(text);
mainWindow.display();
}
return 0;
}
For Windows you can do xxd -i Roboto-Bold.ttf > font_data.txt in git bash. This gives you a file with data that can be imported straight into your project.

OpenCV image dimensions without reading entire image

I'm using OpenCV and am reading gigabytes of images -- too much to fit into memory at a single time. However, I need to initialize some basic structures which require the image dimensions. At the moment I'm using imread and then freeing the image right away, and this is really inefficient.
Is there a way to get the image dimensions without reading the entire file, using opencv? If not could you suggest another library (preferably lightweight, seeing as that's all it'll be used for) that can parse the headers? Ideally it would support at least as many formats as OpenCV.
I don't think this is possible in opencv directly.
Although it isn't specified in the docs, Java's ImageReader.getHight (and getWidth) only parse the image header, not the whole image.
Alternatively here is a reasonable looking lightweight library that definitely only checks the headers, and supports a good amount of image formats.
Finally, if you're on Linux the 'identify ' terminal command will also give you the dimensions, which you could then read in programmatically.
You could use boost gil:
#include <boost/gil/extension/io/jpeg_io.hpp>
int main(int argc, char *argv[])
{
//set/get file_path
auto dims = boost::gil::jpeg_read_dimensions(file_path);
int width = dims.x;
int height = dims.y;
}
You will have to link against libjpeg, by adding -ljpeg flag to the linker. You can get some more information here.

Accessing resources from program in Debian package structure

I've made a DEB package of an C++ app that I've created. I want this app to use resources in the "data" directory, which, in my tests (for convenience), is in the same location that the program binary, and I call it from inside the code by its relative path. In the Debian OS there are standard locations to put the data files in (something like /usr/share/...), and other location to put the binaries in (probably /usr/bin). I'd not like to put the paths hard-coded in my program, I think its a better practice to access an image by "data/img.png" than "/usr/share/.../data/img.png". All the GNU classic programs respect the directories structure, and I imagine they do it in a good manner. I tried to use dpkg to find out the structure of the apps, but that didn't help me. Is there a better way that I'm doing to do this?
PS: I also want my code to be portable to Windows (cross-platform) avoiding using workarounds like "if WIN32" as much as possible.
In your Debian package you should indeed install your data in /usr/share/. When accessing your data, you should use the XDG standard, which states that $XDG_DATA_DIRS is a colon-separated list of data directories to search (also, "if $XDG_DATA_DIRS is either not set or empty, a value equal to /usr/local/share/:/usr/share/ should be used.").
This is not entirely linux specific or debian specific. I think is has something to do with Linux Standard Base or POSIX specifications maybe. I were unable to discover any specification quickly enough.
But you should not use some "base" directory and subdirectories in it for each type of data. Platform dependent code should belong into /usr/lib/programname, platform independent read-only data into /usr/share/programname/img.png. Data changed by application in /var/lib/programname/cache.db. Or ~/.programname/cache.db, depends what kind of application it is and what it does. Note: there is no need to "data" directory when /usr/share is already there for non-executable data.
You may want check http://www.debian.org/doc/manuals/developers-reference/best-pkging-practices.html if packaging for Debian. But it is not resources like in adroid or iphone, or windows files. These files are extracted on package install into target file system as real files.
Edit: see http://www.debian.org/doc/packaging-manuals/fhs/fhs-2.3.html
Edit2: As for multiplatform solution, i suggest you make some wrapper functions. On windows, it depends on installer, usually programs usually have path in registry to directory where they are installed. On unix, place for data is more or less given, you may consider build option for changing target prefix, or use environment variable to override default paths. On windows, prefix would be sufficient also, if it should not be too flexible.
I suggest some functions, where you will pass name of object and they will return path of file. It depends on toolkit used, Qt library may have something similar already implemented.
#include <string>
#ifdef WIN32
#define ROOT_PREFIX "c:/Program Files/"
const char DATA_PREFIX[] = ROOT_PREFIX "program/data";
#else
#define ROOT_PREFIX "/usr/"
/* #define ROOT_PREFIX "/usr/local/" */
const char DATA_PREFIX[] = ROOT_PREFIX "share/program";
#endif
std::string GetImageBasePath()
{
return std::string(DATA_PREFIX) + "/images";
}
std::string GetImagePath(const std::string &imagename)
{
// multiple directories and/or file types could be tried here, depends on how sophisticated
// it should be.
// you may check if such file does exist here for example and return only image type that does exist, if you can load multiple types.
return GetImageBasePath() + imagename + ".png";
}
class Image;
extern Image * LoadImage(const char *path);
int main(int argc, char *argv[])
{
Image *img1 = LoadImage(GetImagePath("toolbox").c_str());
Image *img2 = LoadImage(GetImagePath("openfile").c_str());
return 0;
}
It might be wise to make class Settings, where you can initialize platform dependent root paths once per start, and then use Settings::GetImagePath() as method.

Is it possible to store binary files inside an exe

Is it possible to do this: (for educational purpose).
suppose I have a image file "image.jpg"
I want to create a program when it executes it should create this image. That means the data of the image is stored in the exe. Is this possible to do?
Something like this: link the image file from resource.rc then tell the compiler to get the data and store it (something like this unsigned char data_buffer[]="binary data of the image" then when the program is executed I can write this data to a file)
(I'm using C++ with mingw compiler)
Any help is highly appreciated.
There are several options:
1) Add it as a byte array in a source file. It is trivial to write an auxiliary program that reads the bytes from the files and writes the C source. E.g.:
data_jpg.c:
unsigned char data_jpg[] = {1,2,3... };
data_jpg.h:
extern char data_jpg[];
const size_t data_jpg_size = 1000;
2) Add it as a binary resource to the executable. You said "exe", did you? So you are likely on Windows. Window EXE files can have binary resources, that can be located using the resource API. See the FindResource, LoadResource and GlobalLock, functions.
resource.rc
ID_DATA_JPG FILE "data.jpg"
3) Convert the binary file directly into a OBJ file and link it into the executable. In the old good days of turbo-c used to be a BINOBJ tool for that. And GNU tools can do it, AFAIk, but with MS tools, I really cannot tell.
With a PE file, you can add data(include bin data) to the PE file's tail as your resource. You just remember the PE file's size. But I'm not sure of that whether you need change the PE's checksum. And use VC++ Compiler to embed resources would be pretty much easy.

Embedding cg shaders in C++ GPGPU library

I'm writing a GPGPU Fluid simulation, which runs using C++/OpenGL/Cg. At the moment, the library requires that the user specify a path to the shaders, which is will then read it from.
I'm finding it extremely annoying to have to specify that in my own projects and testing, so I want to make the shader contents linked in with the rest.
Ideally, my .cg files would still be browsable seperately, but a post-build step or pre-processor directive would include it in the source when required.
To make things slightly more annoying, I have a "utils" shader file, which contains functions that are shared among things (like converting 3d texture coords to the 2d atlas equivalent).
I'd like a solution that's cross platform if possible, but it's not so big a deal, as it is currently windows-only. My searches have only really turned up objcopy for linux, but using that for windows is less than ideal.
If it helps, the project is available at http://code.google.com/p/fluidic
You mean you want the shaders embedded as strings in your binary? I'm not aware of any cross-platform tools/libraries to do that, which isn't that surprising because the binaries will be different formats.
For Windows it sounds like you want to store them as a string resource. You can then read the string using LoadString(). Here's how to add them, but it doesn't look like you can link them to a file.
A particularly hacky but cross-platform solution might be to write a script to convert your shaders into a string constant in a header. Then you can just #include it in your code.
I.e. you have the file myshader.shader which contains:
int aFunction(int i, int j)
{
return i/j;
}
And you have a build step that creates the file myshader.shader.h which looks like:
const char[] MYSHADER_SHADER =
"int aFunction(int i, int j)"
"{"
" return i/j;"
"}";
Then add #include "myshader.shader.h" to your code.
Very hacky, but I see no reason why it wouldn't work (except for maybe length/space limits on string literals).
Update: With the release of G++ 4.5 it supports C++0x raw string literals. These can contain new lines 4. I haven't tested it but you should be able to do something like this:
const char[] MY_SHADER = R"qazwsx[
#include "my_shader.c"
]qazwsx";
I haven't tested it though.