picoEXIF library
Problem
Many cameras provide output in MJPEG format, without ability to put in metadata.
All sorts of metadata may be needed, from telemetry to actual camera setting to millisecond timestamps. These can be
placed into the MJPEG headers, or into the JPEG frames themselves, using EXIF format.
As the intended cameras are mostly ESP32-based, the code needed MUST be extra-lightweight and extra-easy to integreate.
Solution approach
- Try to look around the net for some ultralightweight library, find either nothing or heavyweights, fail
- Write it in good ol' C
EXIF structure
TODO: better writeup
Library structure
see comments in the source, TODO: better writeup
Code uses static memory buffer (can be runtime-allocated too), with adjustable size.
Defines:
- EXIF_MAXITEMS - max number of items in the EXIF tag (12 bytes each)
- EXIF_MAXVARBUFLEN - max length of buffer for large variables (only strings for now)
Total size of the buffer is then 20+4+(12*EXIF_MAXITEMS)+EXIF_MAXVARBUFLEN bytes.
As the number of tags and length of strings is usually known in advance, this can be optimized for a given application.
User functions:
- void exif_init() - initializes the JFIF/TIFF header
- void exif_additem(int type,int vartype,long items,long val) - adds a generic up-to-4-byte variable
- void exif_additemstr(int type,char*s) - adds a string variable
- void exif_finish() - calculates variables for the header, adjusts pointers to strings
Output:
- returns two parts of the EXIF chunk - the structured and the freeform
- structured part
- the header and directory, accessible from exif_buf array
- length of the structured part is taken from int exif_gethdrlen() call
- variable-length buffer
- taken from exif_buf array from offset EXIF_BUF_VARBUFSTART
- length of the variable length part is in exif_varbuflen variable
The two arrays/buffers with their lengths then can be outputted, copied, sent to a socket, whatever.
Testing/demo
The test.sh file:
- compiles mkexif.c
- runs it, produces tag file (the entire JFIF FFE1 chunk)
- splices x1hdr.bin, EXIF chunk and x1data.bin into one jpeg file (a random screenshot from underpowered ESPcam, hence the image artefacts)
- runs exiftags and exiftool on the jpeg file, to see output and eventual errors
Download
Archive:
Sources:
Support:
- xtest.jpg - resulting file with generated EXIF tag
Additional utilities:
- jpegchunks.c - feed JPEG from stdin, shows chunks/tags in the file
- exifinsert.c - feed binary chunk from stdin, JPEG filename as argument, stdin data are inserted after APP0/JFIF tag in the JPEG file; handy for inserting third-party generated EXIF or other tags
TODO
- more documentation
- more options for exifinsert, maybe rename to jpeginsert
- detect extraneous data in jpegchunks, maybe rename to jpegtags
If you have any comments or questions about the topic, please let me know here: |