Write jpeg with header comment – boost generic image library (gil)

I had to hack the living daylights out of something today, and although I am not proud of it, needs must where the devil drives!

I was using the boost generic image library (gil) for managing some camera images and using jpeg_write_view() for saving them as JPEGs. A requirement emerged to insert a comment into the header of the saved images, but the gil does not support this out of the box.

The gil uses libjpeg for writing its JPEGs and adding a comment in libjped is as easy as calling jpeg_write_marker(). The problem was that the gil buries libjpeg calls under a few classes so I had to copy and paste some of this in order to redefine a new writer which supports comments.

Anyway I have included the extra code inline below, it adds a new helper function called jpeg_write_view_comment()

Use this new function like this:

 int quality = 70;
 jpeg_write_view_comment("image1.jpg", view, quality, "a comment damn it!!!");

Here is the extra code which I placed in a file called jpeg_writer_comment.h

#pragma once
#include "boost/gil/extension/io/dynamic_io.hpp"
using namespace boost;
using namespace boost::gil;
using namespace boost::gil::detail;
class jpeg_writer_comment : public file_mgr {
    jpeg_compress_struct _cinfo;
    jpeg_error_mgr _jerr;
    void init() {
        _cinfo.err=jpeg_std_error(&_jerr);
        jpeg_create_compress(&_cinfo);
        jpeg_stdio_dest(&_cinfo,_fp.get());
    }
public:
    jpeg_writer_comment(FILE* file)           : file_mgr(file)           { init(); }
    jpeg_writer_comment(const char* filename) : file_mgr(filename, "wb") { init(); }
    ~jpeg_writer_comment() { jpeg_destroy_compress(&_cinfo); }
    template 
    void apply(const View& view,int quality=100, const char* comment = NULL) {
        _cinfo.image_width  = (JDIMENSION)view.width();
        _cinfo.image_height = (JDIMENSION)view.height();
        _cinfo.input_components=num_channels::value;
        _cinfo.in_color_space = jpeg_write_support_private::type,
                                                           typename color_space_type::type>::color_type;
        jpeg_set_defaults(&_cinfo);
        jpeg_set_quality(&_cinfo, quality, TRUE);
        jpeg_start_compress(&_cinfo, TRUE);
        if (comment) {
        	jpeg_write_marker(&_cinfo, JPEG_COM, (const JOCTET*)comment, strlen(comment));
        }
        std::vector::type> > > row(view.width());
        JSAMPLE* row_address=(JSAMPLE*)&row.front();
        for (int y=0;y
    void write_view(const any_image_view& runtime_view) {
        dynamic_io_fnobj op(this);
        apply_operation(runtime_view,op);
    }
};

template 
inline void jpeg_write_view_comment(const char* filename,const View& view,int quality=100, const char* comment = NULL) {
    BOOST_STATIC_ASSERT(jpeg_write_support::is_supported);
    jpeg_writer_comment m(filename);
    m.apply(view, quality, comment);
}