libjpeg example – encode JPEG to memory buffer instead of file

Q: How can I use libjpeg to encode directly to memory on my embedded system without using a file?

A: If you’re encoding images into JPEG on your ARM/Linux embedded platform then you’re most likely using libjpeg, and if you’re encoding quickly then you’re most likely using its drop-in replacement libjpeg-turbo!

Most of the examples of how to use the libjpeg API show how to encode directly to a file, but it’s also possible to use the API to encode to a memory buffer instead. This is handy if you want to transmit the JPEG via MQTT or something and don’t actually need a JPEG file – you can avoid the overhead of writing to your flash filesystem and having to read the data from it before sending.

Of course, one easy way of achieving this if your embedded system has a RAM disk (as a lot of ARM/Linux based systems will) is to just get libjpeg to encode to file on the RAM disk, in this way you can avoid writing to flash, however you will still have to open the file and read in all of the data into a buffer afterwards.

The trick to getting libjpeg to encode directly to  memory is make a call to jpeg_mem_dest() (instead of to jpeg_stdio_dest() for a file), this allows the caller to specify an output buffer for the jpeg data (as well as its size).

You can either supply a pointer to a buffer, or if you pass NULL, the library will allocate a buffer for you – either way, you must free() the output buffer once you are finished with it!

Some things to note are:

  • You can pass in a pointer to a buffer that you have already malloc()’ed
  • If you pass in NULL, the lib will allocate a buffer for you.
  • If the buffer that you specify (or that the lib automatically malloced()’ed) turns out to be too small to hold the JPEG data then the lib will free() the buffer and malloc() a new one (this will probably also involve a memory copy).
  • After encoding the size variable will contain the number of JPEG bytes in the output buffer (i.e. it no longer contains the size of the buffer used!)
  • If you want to re-use the same buffer for each encode, then just pass in the same buffer pointer each time with it’s original size and don’t free() it after encoding.

Here is an example of a c++ function that encodes to memory, it uses a buffer that’s allocated by the library:

The we can use this function to encode an 8bit image like this: