-
Notifications
You must be signed in to change notification settings - Fork 164
Code Samples
Christian Henning edited this page Mar 22, 2018
·
19 revisions
Gil strength is its expressiveness by using concepts and plenty of meta-programming. This makes gil hard to learn and worse hard to extend without creating a mess.
This wiki will show some of the power of gil.
// Always assume
#include <vector>
#include <boost/gil/gil_all.hpp>
using namespace std;
using namespace boost::gil;
How to get the color space type from an image/view?
typedef rgb8_image_t image_t;
typedef typename color_space_type<image_t::view_t::value_type>::type colour_space_t;
There are rgb8_pixel_t
, bgr8_pixel_t
, and any other number of channel combinations. So, how do you get the red channel value?
auto get_red(pixel_t p)
{
return get_color(p, red_t());
}
Each pixel type is defined with a bunch of channel types. Look here for the correct way of defining a new pixel type.
Damn it, my image is interleaved but I only want the red values!
argb8_image_t img( 640, 480 );
fill_pixels(view(img), argb8_pixel_t(0, 255, 0, 0 ));
// get a view to the first channel
auto v = nth_channel_view( view(img), 1 );
// convert the first channel view to gray8
auto c = color_converted_view<gray8_pixel_t>( v );
Generic way for hashing pixels. We are using static_for_each()
to loop through all channels of a pixel.
#include <unordered_map>
template< typename Pixel >
struct pixel_hasher
{
std::size_t operator()( const Pixel& p ) const
{
typedef channel_type<Pixel>::type channel_t;
std::size_t hash = 0;
static_for_each( p, [&] ( const channel_t& c )
{
boost::hash_combine(hash, c);
});
return hash;
}
};
void test()
{
typedef rgb8_pixel_t pixel_t;
pixel_t p( 1,2,3);
unordered_map< pixel_t, int, pixel_hasher< pixel_t > > n;
n[p] = 99;
}
#include <SFML/Graphics.hpp>
#include <cassert>
#include <complex>
#include <iostream>
#include <boost/gil/gil_all.hpp>
#include <boost/gil/extension/toolbox/color_spaces/hsv.hpp>
#ifdef _DEBUG
const int width = 640; //1024;
const int height = 480; //768;
#else
const int width = 1024;
const int height = 768;
#endif
template< typename T = double >
struct coloring_info
{
coloring_info()
: _inside( true )
{}
coloring_info( bool inside, const std::complex< T >& value, int iterations, int max_iterations )
: _inside( inside )
, _value( value )
, _iterations( iterations )
, _max_iterations( max_iterations )
{}
sf::Color get_color() const
{
sf:: Color color;
color.a = 255;
using namespace boost;
using namespace gil;
hsv32f_pixel_t src( ( _iterations % 256 ) / 255.f // hue
, 1.f // (full) saturation
, ( _iterations < _max_iterations ) ? 1.f : 0.f // value
);
rgb8_pixel_t dst;
color_convert(src, dst);
color.r = gil::get_color(dst, red_t());
color.g = gil::get_color(dst, green_t());
color.b = gil::get_color(dst, blue_t());
if( _inside )
{
color = sf::Color::Black;
}
else
{
if( _iterations < _max_iterations )
{
// point does not belong to Mandelbrot set
int r = static_cast<int>(( 255.0 / _max_iterations ) * _iterations );
if( _iterations < ( _max_iterations / 2 ))
{
color.r = r;
color.g = 0;
color.b = 0;
}
else
{
color.r = r;
color.g = 255;
color.b = 255;
}
color.r;
color.g;
color.b;
}
}
return color;
}
bool _inside;
std::complex< T > _value;
int _iterations;
int _max_iterations;
};
template< typename T = double >
struct fractal_parameters
{
// set all parameters by hand
fractal_parameters( T r_min, T r_max, T i_min, T i_max, int max_iterations, int width , int height )
: _real_min(r_min)
, _real_max(r_max)
, _imag_min(i_min)
, _imag_max(i_max)
, _max_iterations( max_iterations )
, _real( 0 )
, _imag( 0 )
{
// real_max = 1.0
// real_min = -2.0
// imag_max = 2.0
// imag_min = -1.2
// width = 640
// height = 480
// x_step = ( 1 + 2 ) / 639 = 0.005
// y_step = ( 2 + 1.2 ) / 479 = 0.007
_x_step = ( _real_max - _real_min ) / ( width - 1 );
_y_step = ( _imag_max - _imag_min ) / ( height - 1 );
}
// scales to include aspect ration
fractal_parameters( T r_min, T r_max, T i_min, int max_iterations, int width , int height )
: _real_min(r_min)
, _real_max(r_max)
, _imag_min(i_min)
, _max_iterations( max_iterations )
, _real( 0 )
, _imag( 0 )
{
_imag_max = _imag_min + ( _real_max - _real_min ) * height / width;
_x_step = ( _real_max - _real_min ) / ( width - 1 );
_y_step = ( _imag_max - _imag_min ) / ( height - 1 );
}
// real_min represents x = 0 or the left boundary of the image
void set_x( int x ) { _real = _real_min + x * _x_step; }
// imag_max represents y = 0 or the upper boundary of the image
void set_y( int y ) { _imag = _imag_max - y * _y_step; }
coloring_info<> calc() const
{
coloring_info<> ci;
std:: complex< T> c( _real, _imag );
std:: complex< T> Z( c );
int n;
for( n = 0; n < _max_iterations; ++n )
{
if( std::abs( Z ) > 2.0 )
{
ci._inside = false;
break;
}
Z = Z * Z + c;
}
ci._iterations = n;
ci._max_iterations = _max_iterations;
return ci;
}
T _real_min;
T _real_max;
T _imag_min;
T _imag_max;
T _x_step;
T _y_step;
int _max_iterations;
T _real;
T _imag;
};
// upper left is 0,0
void set_pixel( sf::Image & image , int x , int y , unsigned char r = 255, unsigned char g = 255, unsigned char b = 255 )
{
image.setPixel( x, y, sf:: Color( r, g, b, 255));
}
void set_pixel( sf::Image & image , int x , int y , sf::Color c )
{
image.setPixel( x, y, c );
}
void paint( sf::Image & image , sf::Color c )
{
for( int y = 0; y < height; ++y )
{
for( int x = 0; x < width; ++x )
{
set_pixel( image, x, y, c.r, c.g, c.b );
}
}
}
void redraw( sf::Image & image , fractal_parameters <> mandel_brot )
{
//paint(image, sf::Color::Black);
sf::Color color;
for( int y = 0; y < height; ++y )
{
mandel_brot.set_y( y );
for( int x = 0; x < width; ++x )
{
mandel_brot.set_x( x );
auto ci = mandel_brot.calc();
set_pixel( image, x, y, ci.get_color() );
}
}
}
int main()
{
sf::RenderWindow window(sf:: VideoMode(width, height), "Title");
window.setFramerateLimit( 30 );
sf::Texture texture;
if( !texture.create(width, height))
{
exit(1);
}
sf::Image image;
image.create(width, height);
fractal_parameters<> mandel_brot_1( -2.0, 1.0, -1.2, 50, width, height );
fractal_parameters<> mandel_brot_2( -2.0, 1.0, -1.2, 300, width, height );
//max_iterations++;
redraw( image, mandel_brot_1 );
while (window.isOpen())
{
sf:: Event event;
while (window.pollEvent(event))
{
switch(event.type)
{
case sf:: Event:: Closed:
{
window.close();
break;
}
case sf:: Event:: KeyPressed:
{
if( sf:: Keyboard::isKeyPressed( sf:: Keyboard:: Right ))
{
std::cout << "right" << std::endl;
std::cout << "begin" << std::endl;
redraw( image, mandel_brot_2 );
std::cout << "end" << std::endl;
}
else if( sf:: Keyboard::isKeyPressed( sf:: Keyboard:: Left ))
{
std::cout << "left" << std::endl;
std::cout << "begin" << std::endl;
redraw( image, mandel_brot_1 );
std::cout << "end" << std::endl;
}
break;
}
}
}
texture.update(image);
sf:: Sprite sprite(texture);
window.clear();
window.draw(sprite);
window.display();
}
return 0;
}
#include <boost/test/unit_test.hpp>
#include <boost/gil/gil_all.hpp>
using namespace std;
unsigned int width = 640;
unsigned int height = 480;
// format is ARGB8888 -> 4 bytes
// scanline size in bytes
unsigned int scanline = width * sizeof( Uint32 );
unsigned int frame_size = scanline * height;
SDL_Renderer* ren = NULL;
SDL_Texture* tex = NULL;
Uint32* pixels = NULL;
Uint32 draw( Uint32 interval, void* param )
{
using namespace boost;
using namespace gil;
argb8_view_t v = interleaved_view( width, height, (argb8_pixel_t*) pixels, scanline );
fill_pixels( v, argb8_pixel_t( 255, 255, 0 , 0 ));
//memset( pixels, 0, frame_size );
SDL_UpdateTexture( tex, NULL, pixels, scanline );
SDL_RenderClear( ren );
SDL_RenderCopy( ren, tex, NULL, NULL );
SDL_RenderPresent( ren );
return interval;
}
BOOST_AUTO_TEST_CASE( sdl_test )
{
if( SDL_Init( SDL_INIT_EVERYTHING ) == -1 )
{
cout << SDL_GetError() << endl;
}
// Create Window
SDL_Window* win = SDL_CreateWindow( "First"
, 100
, 100
, width
, height
, SDL_WINDOW_SHOWN
);
if( win == NULL )
{
cout << SDL_GetError() << endl;
}
// Create Renderer
ren = SDL_CreateRenderer( win
, -1 // SDL selects video driver
, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC
);
if( ren == NULL )
{
cout << SDL_GetError() << endl;
}
tex = SDL_CreateTexture( ren
, SDL_PIXELFORMAT_ARGB8888
, SDL_TEXTUREACCESS_STREAMING
, width
, height
);
if( tex == NULL )
{
cout << SDL_GetError() << endl;
}
pixels = (Uint32*) malloc( frame_size );
// Add Timer
SDL_AddTimer( 100, draw, NULL );
// Wait for user to quit
bool quit = false;
SDL_Event e;
while( quit == false )
{
while( SDL_PollEvent( &e ))
{
if( e.type == SDL_WINDOWEVENT )
{
auto id = e.window.windowID;
break;
}
if( e.type == SDL_QUIT )
{
quit = true;
break;
}
if( e.type == SDL_KEYDOWN )
{
quit = true;
break;
}
}
}
// Clean up
SDL_DestroyTexture( tex );
SDL_DestroyRenderer( ren );
SDL_DestroyWindow( win );
SDL_Quit();
}