3rdParty/boost/1.78.0/libs/gil/doc/html/design/extending.html
You can define your own pixel iterators, locators, image views, images, channel types, color spaces and algorithms. You can make virtual images that live on the disk, inside a jpeg file, somewhere on the internet, or even fully-synthetic images such as the Mandelbrot set. As long as they properly model the corresponding concepts, they will work with any existing GIL code. Most such extensions require no changes to the library and can thus be supplied in another module.
Each color space is in a separate file. To add a new color space, just copy one of the existing ones (like rgb.hpp) and change it accordingly. If you want color conversion support, you will have to provide methods to convert between it and the existing color spaces (see color_convert.h). For convenience you may want to provide useful typedefs for pixels, pointers, references and images with the new color space (see typedefs.h).
Most of the time you don’t need to do anything special to use a new channel type. You can just use it:
typedefpixel\<double,rgb\_layout\_t\>rgb64\_pixel\_t;// 64 bit RGB pixeltypedefrgb64\_pixel\*rgb64\_pixel\_ptr\_t;// pointer to 64-bit interleaved datatypedefimage\_type\<double,rgb\_layout\_t\>::typergb64\_image\_t;// 64-bit interleaved image
If you want to use your own channel class, you will need to provide a specialization of channel_traits for it (see channel.hpp). If you want to do conversion between your and existing channel types, you will need to provide an overload of channel_convert.
Suppose you want to provide your own color conversion. For example, you may want to implement higher quality color conversion using color profiles. Typically you may want to redefine color conversion only in some instances and default to GIL’s color conversion in all other cases. Here is, for example, how to overload color conversion so that color conversion to gray inverts the result but everything else remains the same:
// make the default use GIL's defaulttemplate\<typenameSrcColorSpace,typenameDstColorSpace\>structmy\_color\_converter\_impl:publicdefault\_color\_converter\_impl\<SrcColorSpace,DstColorSpace\>{};// provide specializations only for cases you care about// (in this case, if the destination is grayscale, invert it)template\<typenameSrcColorSpace\>structmy\_color\_converter\_impl\<SrcColorSpace,gray\_t\>{template\<typenameSrcP,typenameDstP\>// Model PixelConceptvoidoperator()(constSrcP&src,DstP&dst)const{default\_color\_converter\_impl\<SrcColorSpace,gray\_t\>()(src,dst);get\_color(dst,gray\_color\_t())=channel\_invert(get\_color(dst,gray\_color\_t()));}};// create a color converter object that dispatches to your own implementationstructmy\_color\_converter{template\<typenameSrcP,typenameDstP\>// Model PixelConceptvoidoperator()(constSrcP&src,DstP&dst)const{typedeftypenamecolor\_space\_type\<SrcP\>::typeSrcColorSpace;typedeftypenamecolor\_space\_type\<DstP\>::typeDstColorSpace;my\_color\_converter\_impl\<SrcColorSpace,DstColorSpace\>()(src,dst);}};
GIL color conversion functions take the color converter as an optional parameter. You can pass your own color converter:
color\_converted\_view\<gray8\_pixel\_t\>(img\_view,my\_color\_converter());
You can provide your own pixel iterators, locators and views, overriding either the mechanism for getting from one pixel to the next or doing an arbitrary pixel transformation on dereference. For example, let’s look at the implementation of color_converted_view (an image factory method that, given any image view, returns a new, otherwise identical view, except that color conversion is performed on pixel access). First we need to define a model of PixelDereferenceAdaptorConcept; a function object that will be called when we dereference a pixel iterator. It will call color_convert to convert to the destination pixel type:
template\<typenameSrcConstRefP,// const reference to the source pixeltypenameDstP\>// Destination pixel value (models PixelValueConcept)classcolor\_convert\_deref\_fn{public:typedefcolor\_convert\_deref\_fnconst\_t;typedefDstPvalue\_type;typedefvalue\_typereference;// read-only dereferencingtypedefconstvalue\_type&const\_reference;typedefSrcConstRefPargument\_type;typedefreferenceresult\_type;staticboolconstexpris\_mutable=false;result\_typeoperator()(argument\_typesrcP)const{result\_typedstP;color\_convert(srcP,dstP);returndstP;}};
We then use the add_deref member struct of image views to construct the type of a view that invokes a given function object (deref_t) upon dereferencing. In our case, it performs color conversion:
template\<typenameSrcView,typenameDstP\>structcolor\_converted\_view\_type{private:typedeftypenameSrcView::const\_t::referencesrc\_pix\_ref;// const reference to pixel in SrcViewtypedefcolor\_convert\_deref\_fn\<src\_pix\_ref,DstP\>deref\_t;// the dereference adaptor that performs color conversiontypedeftypenameSrcView::templateadd\_deref\<deref\_t\>add\_ref\_t;public:typedeftypenameadd\_ref\_t::typetype;// the color converted view typestatictypemake(constSrcView&sv){returnadd\_ref\_t::make(sv,deref\_t());}};
Finally our color_converted_view code simply creates color-converted view from the source view:
template\<typenameDstP,typenameView\>inlinetypenamecolor\_converted\_view\_type\<View,DstP\>::typecolor\_convert\_view(constView&src){returncolor\_converted\_view\_type\<View,DstP\>::make(src);}
(The actual color convert view transformation is slightly more complicated, as it takes an optional color conversion object, which allows users to specify their own color conversion methods). See the GIL tutorial for an example of creating a virtual image view that defines the Mandelbrot set.