Archive for the ‘zlib’ Tag

I Knew it was too easy – part 2   Leave a comment


At the end of the the post “I knew it was too easy” I mentioned that easiest method to get the parameter data out of Saturn seed files was to read the file directly and extract the keys and their values from the tEXt chunks. It was simple to implement and so I continued with development of version 4.0.0 of Saturn, today I noticed that when loading a seed file the wrong colour map was used, a colour map called Greyscale was unexpectedly used. The Greyscale colour map is a simple “auto” generated colour map which is defined as a single cycle sine wave for the red, green and blue components, the expected colour map was also an auto generated colour map. The problem turns out to be that the keys, “colour0”, “colour1” and “colour2” and their data were not extracted from the seed file, so that when the data was requested empty strings were returned and the default values were used instead which corresponds to the Greyscale colour map.

So why weren’t the keys and their data extracted from the seed file? Using a Linux utility called pngmeta all the keys and their data can be printed for any PNG file and that showed that the seed file did indeed contain the keys and their data for the “auto” generated colour map. But what exactly is in the file? Using a hex editor the answer is that Qt had embedded the colour map data using zTXt chunks and not tEXt chunks. The difference between zTXt and tEXt is that zTXt compresses the data but not the key, the data for the “colour0” was 46 characters, the length of the compressed data in the zEXt chunk is 120 bytes, the length of the data for “colour1” and “colour2” are 48 bytes each and the compressed size is again 120 bytes. This makes no sense, the compressed data is larger than the data to be compressed!

PNG files only support zlib compression (as far as I know). I initially looked for documentation on zlib which of course would have a C interface. Saturn is written in C++ so some method of accessing zlib’s functionality from C++ would be preferred, my initial thought was “Does Boost handle zlib decompression?”, after a bit of searching the answer is, “Yes, it does”.

I loaded the compressed data into a std::vector and then passed it to a utility routine to convert it into std::string:

std::string uncompress(std::vector<char>& buffer)
{
    std::string str;
    io::filtering_ostream os;
    os.push(io::zlib_decompressor());
    os.push(io::back_inserter(str));
    int size = buffer.size();
    for (int i = 0; i < size; i++)
    {
        os.put(buffer[i]);
    }
    // the above loop could be replaced using
    //
    // os.write(reinterpret_cast<char*>(&buffer[0]), buffer.size());
    //
    // or
    //
    // os.write(buffer.data(), buffet.size()); // C++11
    //
    return str;
}

A fragment of code on its own, usually results in questions such as “Where is io defined?” and “What headers should I include?”, so here are the missing pieces required to compile the code:

#include <boost/iostreams/device/back_inserter.hpp>
#include <boost/iostreams/filtering_stream.hpp>
#include <boost/iostreams/filter/zlib.hpp>

namespace io = boost::iostreams;

At one time the different path delimiters used on Windows and Unix/Linux meant that different include statements had be used and were selected by condition compilation, fortunately the Microsoft C++ compiler I use happily accepts Unix style delimiters.

I’ve used some C++11 features in my code, I would use more except that compiler support is not yet complete and as I release Saturn and Titan for Linux and Windows I have to take account of the compiler that has the least support and that is Microsoft’s. The sooner better C++11 support is more widespread the better as much cleaner code can written.

So now all the embedded data can be extracted from Saturn seed files, so the next release is one step closer.

Posted 8 May 2013 by element90 in Programming, Software

Tagged with , , , ,