A short follow up and sample program which demonstrates how to write a RIFF palette with ease.
I covered the basics of the RIFF specification and how to read palettes in my previous article.
When I first started this journey and wrote how to read and write palette files in different formats, the code I provided generally read and wrote bytes one at a time. At the start of January (2016, time has a habit of getting away from me!) I wrote an article which described how to read and write farbfeld images.
While updating the source for this project, I created a series of benchmarks testing the serialisation code and proved the obvious fact that reading and writing a byte a time was really inefficient.
As a result of this, I'm now a little more careful when reading and writing files. The previous article on reading RIFF palettes tried to be efficient both in terms of IO (reading blocks of information at a time) and in terms of allocations (by using the same buffer object as much as possible), so hopefully that code is quite efficient.
Similarly, when writing the file as per the code below, I create a buffer large enough to hold the entire RIFF form - palettes generally aren't huge objects so this is fine. I then populate the buffer with the form and write it all at once.
There aren't any guards around this code though to ensure that buffers are reasonably sized and so if this code was being adapted (for example to read WAVE audio or AVI videos) then additional precautions would be required.
As we're going to construct the entire RIFF form in a byte
array, we can't use classes such as
StreamWriter to write
values. I'm going to use a pair of helper methods that will
break down an
int into four bytes or a
ushort into a pair of
bytes which I will then place into the array at appropriate
Remember that RIFF uses little-endian ordering
You could use the
BitConverterclass to break down the values, but that means extra allocations for the byte array returned by the
First we need to calculate the size of our
data chunk for the
palette, which is
4 + number_of_colors * 4. Each colour is
4 bytes, which accounts for the bulk of the
chunk, but there's also
4 bytes for the
palNumEntries fields of the
Once we have that size, we calculate the size of the complete RIFF form and create a byte array that will hold the entire form.
Next, we write the RIFF header. Remember that the document size is the size of the entire form minus 8 bytes representing the RIFF header.
We then follow this with the form type
So far so good. We won't be writing any meta data, only the
data chunk with our basic RGB palette. First we'll write the
chunk header, and then we'll write the first two fields
describing the palette.
Now it's just a case of filling in the colour information
And finally, we can write our buffer to the destination stream. Easy!
- 2017-03-04 - First published
- 2020-11-22 - Updated formatting
Like what you're reading? Perhaps you like to buy us a coffee?