best image format for bare metal application? - Page 1
Forum section: electronics / general

author: DiTBho
author_rank: Super Contributor
timestamp: June 12, 2025, 09:24:02 pm
content: So, my bootloader now needs to display an image.I wonder what the best video format is.It should:- be easy to understand and parse (2)- be easily convertible to C array- be used with { 16, 24} bit per pixel- not lose information (like JPEG)- RGB, alpha is optional (not needed)I see some older firmwares using "xpm-v2"(2).I personally only use "png" for my web content, but I have NO experience with SDL/C programs that directly access the GNU/Linux framebuffer.(e.g. { fbi, fim(1) ... } )In my case, I don't have Linux installed, but I implemented a framebuffer to handle the display.This means that the code "should" be developed and tested on a GNU/Linux machine with a simple - not accelerated - /dev/fb, and then ported to the final target (of course, retesting everything).(1) fim, seehere, "fbi-improved".(2) xpm needs a parser

author: SiliconWizard
author_rank: Super Contributor
timestamp: June 12, 2025, 09:39:11 pm
content: Why not use PNG? (Unless you're very short on available code size for your bootloader.)When I don't want to use libpng, I use stb_image:https://github.com/nothings/stb/tree/masterit's a single header file and works a treat: stb_image.h

author: cunningfellow
author_rank: Regular Contributor
timestamp: June 12, 2025, 09:45:34 pm
content: What is the image? Is it a photo or a logo with flat areas of colour? What does bootloader mean. Obviously not 512bytes of optiboot in an ATMega328p. Does bootloader mean kilobytes of space or megabytes of space and do you need to try minimize the space used?

author: mariush
author_rank: Super Contributor
timestamp: June 12, 2025, 09:47:12 pm
content: TGA or a subset of TGA (parts you're interested in) :http://www.paulbourke.net/dataformats/tga/orhttps://www.fileformat.info/format/tga/egff.htmPCX can also be an option :https://www.fileformat.info/format/pcx/spec/a10e75307b3a4cc49c3bbe6db4c41fa2/view.htmIrfanview and other image viewers / editors support exporting images to these formats.QOI can compress - well, technically not compression, more like using filters and run length encoding - surprisingly well and it's super easy to decode (but limited in color formats and features) :https://qoiformat.org/qoi-specification.pdfPPM is super basic file format:https://netpbm.sourceforge.net/doc/ppm.htmlbut i really don't like that the header can be variable length and that you're supposed to read the header as text lines and that lines with # in front are comments and can appear before or after lines that hold information ...If you strip all the extra stuff your header will always be two lines, so you will know the data starts after the second set of CR LF and parse it easily line by line. Doesn't have support for color palettes though, so that sucks, with tga or pcx you can save some space with color palettes.

author: DiTBho
author_rank: Super Contributor
timestamp: June 12, 2025, 11:05:18 pm
content: Quote from: cunningfellow on June 12, 2025, 09:45:34 pmbig logo, 640x480, with flat areas of colour.Only two colors: white, black.Quote from: cunningfellow on June 12, 2025, 09:45:34 pm512Kbyte of flash space for the whole firmware.At the moment, I am consuming 120Kbyte.But I address up to 56Mbyte of ram.Once loaded, the kernel will be able to address up to 64Mbyte of ram.But no way to address the flash ...

author: DiTBho
author_rank: Super Contributor
timestamp: June 12, 2025, 11:13:29 pm
content: Quote from: mariush on June 12, 2025, 09:47:12 pmI found ppm in a bootloader that implements a graphical GUI with menus and icons, and it has the same space constraints as mine.Or rather, they have 1Mbyte available (including fonts, icons, and a small logo), a little more than I have.I have not studied their code yet, opening it and giving a quick look, I did not like the parser very much, precisely for the things you describe.

author: DiTBho
author_rank: Super Contributor
timestamp: June 12, 2025, 11:18:31 pm
content: Umm, the whole display is 640x480, but the part of the pixels that describes the logo can be enclosed in a rectangle of 200x300 pixels.So I could "paint" the screen black, which is the background color of the logo, and then use the x and y offsets to display the logo.Maybe you'll save some space.

author: mariush
author_rank: Super Contributor
timestamp: June 12, 2025, 11:34:46 pm
content: PBM is portable binary (black and white), each bit in a byte is one pixel... PGM is portable graymap (256 shades of gray)For monochrome images, you could use the plain old boring BMP, but keep in mind the BMP file format loads from bottom to top (the first line of pixels you read is the bottom most line on screen)But the BMP format has a 2 color option so each line of your logo would use 640 / 8 = 80 bytes which is a multiple of 4 so that's cool (the format is padded to multiple of 4 bytes per line) so your 640x480 logo would use 38400 bytes + headers.If you make your bitmap as 16 color / 4 bit per pixel (and store your black and white as 2 colors in the palette) you then have the option to use RLE compression - downside is you can't really seek into the file to load one row at a time and draw it on the screen.Seehttps://www.fileformat.info/format/bmp/spec/e27073c25463436f8a64fa789c886d9c/view.htmps technically GIF would also be an option ... the patents are expired and a lzw decoder is quite easy to implementseehttps://giflib.sourceforge.net/whatsinagif/lzw_image_data.html

author: brucehoult
author_rank: Super Contributor
timestamp: June 12, 2025, 11:54:27 pm
content: Quote from: DiTBho on June 12, 2025, 11:05:18 pmIt isonlywith long runs (and areas) of the same pixel colour? No dithered areas at all? Just simple run-length encoding. Like, alternating bytes saying "N white pixels", "N black pixels", "N white pixels". If there are more than e.g. 255 same colour pixels in a row then there'll be a byte saying "0 xxx pixels".Maybe a quadtree.Maybe compress a target-format pixelmap using lz4. The decoder is very small and fast (like, 40 instructions in RV32I, much smaller than zlib), but adapts well to all kinds of data.

author: mikeselectricstuff
author_rank: Super Contributor
timestamp: June 13, 2025, 12:12:10 am
content: For very simple video handling, uncompressed AVI.Super easy to deal with - jump through a couple of offsets in the header and then it's just a sequence of bitmaps with 8 bytes between them. There is a frame pointer list at the end but you don't need to use it.Also easy to have audio if you need - just interleaves audio blocks between each frameSupports 8, 16 (rgb565) and 24bppThere is an excellent Windows tool called Virtualdub, which is a super easy way to prepare AVIs, has simple timeline crop, cut/paste etc., filters for stuff like resizing, brightness adjust, flip/rotate etc.It can handle pretty much any format - I use if for LED displays with oddball formats like 8x16, 1056x1, 32x128 etc.It even supports RGB 565 for 16-bit LCDs - I wrote a plugin for it to dither 24 bit colour down to rgb565It can covert from MPEG and a few others, including sequences of BMP/JPG stillsBut if it's just a still image you need, BMP is very simple

author: forrestc
author_rank: Unknown
timestamp: June 13, 2025, 12:32:35 am
content: Quote from: DiTBho on June 12, 2025, 11:05:18 pmThe simplest encoding is 1 bit per pixel. 640x480=307200 bits. Packed into 8 bits per byte = 38,400 bytes. You don't need a 'file format'; just an array of bytes, with each bit representing 1 for white and 0 for black.As another poster mentioned, for certain types of images, run-length encoding may be more suitable. It really depends on how many ones or zeros are in a row in your image. For example, if you have a row that's 00001110000000, you can encode it into three numbers: 4, 3, and 6. (4 zeros, 3 ones, 6 zeros).Assuming you encode this as an 8 bit byte per 'count', you can handle up to 255 1's or 0's in a row. If you had more than 255 of a one or a zero in a row, you can insert a zero to continue on without outputting any of the other color.The disadvantage of run length encoding is that it doesn't work for images with lots of 'runs' of less than 8 bits, as that can cause expansion. The worst case of a string of 10101010 would expand one byte of data into eight bytes: 1,1,1,1,1,1,1,1. You'd need to do some experiments into what works best for your situation.

author: brucehoult
author_rank: Super Contributor
timestamp: June 13, 2025, 01:32:52 am
content: Quote from: forrestc on June 13, 2025, 12:32:35 amPrecisely what I said.QuoteWhich is where lz4 is great. It also has maximum RLE compression of 255:1, but alternates copied patterns (of any length) with groups of any number of literal bytes. In the case of completely incompressible data (everything is literal bytes) the data is expanded by one byte per 255 data bytes. And the code is very very simple and small, and runs at essentially memcpy() speed (in fact often closer to memset() if you have a cache).

author: Siwastaja
author_rank: Super Contributor
timestamp: June 13, 2025, 08:52:07 am
content: Quote from: DiTBho on June 12, 2025, 11:18:31 pm200*300/8 = 7500 bytes, seems to fit without any "file format" or any compression - just the raw pixels. So don't overcomplicate it. Write a simple tool which imports file in format of your preference (e.g. png, using libpng) and outputs uint8_t array[] = { } which you can then #include to your firmware code.

author: brucehoult
author_rank: Super Contributor
timestamp: June 13, 2025, 10:20:50 am
content: Quote from: Siwastaja on June 13, 2025, 08:52:07 amOne criterion was "used with { 16, 24} bit per pixel", even though each pixel is apparently only black or white.So that 7500 byte bitmap in fact needs 16:1 or 24:1 decompression, or else is actually 120,000 or 180,000 bytes. In which case you might as well do at least RLE or lz4. I would even if it's 7500 bytes, as the decompress code will be on the order of 100 bytes.

author: DiTBho
author_rank: Super Contributor
timestamp: June 13, 2025, 10:35:11 am
content: At the moment the logo is 1-bit color, but ... Who knows if in the future it will be "graphically" improved to something more "artistic".Just be ready.

author: DiTBho
author_rank: Super Contributor
timestamp: June 13, 2025, 01:06:11 pm
content: For another project, I also have the opposite problem: choosing the right format to save screenshots!In this case it is a "VGA-grabber" that I am reverse engineering.At the moment, I take an image from the VGA and transfer the pixels directly into the x11 viewer that I wrote just to test everything.I need a way to save screenshots.I am talking about 1024x768@rgb-888.ideally something that can take as little time as possible to save screenshots

author: mariush
author_rank: Super Contributor
timestamp: June 13, 2025, 02:11:28 pm
content: You can write uncompressed PNG images - the only complexity is calculating CRC32 of each chunk, but any modern processor can calculate CRC32 at tens of megabytes per second.You just write your IHDR chunk, one or multiple IDAT chunks (up to you if you use one big block or multiple) and one IEND chunk (you need to calculate a CRC32 for each of these chunks and append to end of chunk but it's easy.You can store the actual image in uncompressed format, without filters enabled, no compression, so it would be super fast. But you could also simply use zlib to deflate the buffer and store as compressed PNG.If you want some fast"compression" easiest and very fast would be QOI format I already mentioned :https://qoiformat.org/and if you don't mind flipping the images vertically afterwards, saving to BMP is always an easy option (just don't forget to pad each row to multiple of 4 bytes)

author: SiliconWizard
author_rank: Super Contributor
timestamp: June 13, 2025, 03:45:31 pm
content: For writing PNG, the libraries I mentioned also have that: stb_image_write.h. It's pretty fast (much faster than with libpng, but with a lower compression ratio - but definitely good enough here.)Now if you don't need compression, using a raw format such as bmp, tga, ... is dead simple. Just a simple header followed by raw pixel data, all fully documented.

author: radiolistener
author_rank: Super Contributor
timestamp: June 13, 2025, 10:59:56 pm
content: Quote from: SiliconWizard on June 13, 2025, 03:45:31 pmyes, using bmp is pretty simple and it is supported on different OS.