This is a handy tool for embedding images inside your C++ binary.
Introduction
If you've coded significantly for IoT, you've probably run into situations where you need bitmapped pixel data from images made available to your code. These little devices can't just take JPG or PNG resources and display them.
IoT may not be the only time you need something like this. It may be useful for embedding little toolbar or icon images if you're targeting platforms that don't have a resource fork in the binary.
Using this Mess
First, there are two executables: img2cpp and img2cppw. They both do the same thing, but the former is a command line tool and the latter is a GUI based tool. Let's take a look at the usage screen for the command line tool, which will help clarify both:
Usage: img2cpp.exe <imagefile> [/name <name>] [/jpg|/16bpp]
[/gfx14|/gfx17] [/be]
[/resize [<width>][x<height>]]
[/arduino] [/out: <headerfile>]
<imagefile> The image to convert
<name> The base name to use in the header
<jpg> Embed as JPG image
<16bpp> Convert to 16bpp
<gfx14/gfx17> Use gfx14 or 17 bindings
<be> Use big-endian format
<resize> Resize the image. If one dimension
isn't specified, the aspect ratio
is preserved.
<arduino> Create code for Arduino
<headerfile> The output header to generate
imagefile
can be any image.
The name
will indicate the name of the image in your code. Depending on the code generated, referring to this name will either get you to the byte array for the pixels (cpp), or to the actual bitmap for the pixels (gfx14/gfx17). Referring to <name>_size
will get you to a struct that indicates the size of the bitmap.
jpg
indicates that the embedded data will be a JPG stream. This option is not compatible with be
or 16bpp
.
16bpp
means the pixel data should be converted to RGB565 format. Otherwise, it will be RGB888.
gfx14
/gfx17
indicates that code will be generated that uses the htcw_gfx graphics library, using either the C++14 or the C++17 standard.
be
indicates that big endian output should be used. Often, for IoT, this is the case, since most of the display controllers expect pixel data in big endian format.
resize
indicates that the image should be resized. The format is <width>x<height>
to resize for both the width and the height, <width>
, to resize the width and maintain the aspect ratio or x<height>
to do the same but with the height.
arduino
indicates that code should be generated for the Arduino framework. The array will be created in program flash (PROGMEM
).
headerfile
indicates the output file to use. If the command line doesn't specify this, output is directed to stdout.
Coding this Mess
Once your header file is generated and included into your project, how you use it depends on the type of code generated. The following snippets assume name
from above is my_image
.
Standard C++
const uint8_t* px0ptr = my_image;
uint16_t width = my_image_size.width;
uint16_t height = my_image_size.height;
There is of course, no drawing code included with this. It's up to you to render or otherwise use the pixel data in your code.
gfx14/gfx17
const uint8_t* px0ptr = my_image_data;
uint16_t width = my_image_size.width;
uint16_t height = my_image_size.height;
my_image_t bmp = my_image;
With htcw_gfx, you can draw my_image
to your lcd
like so:
draw::bitmap(lcd,lcd.bounds(),my_image,my_image.bounds());
Disclaimer
I haven't tested all combinations of options yet. If you find something that doesn't work for you, leave a remark in the comments and I'll get on it.
History
- 29th June, 2022 - Initial submission
- 29th June, 2022 - Fixed bug with jpg generation under gfx