TuttleOFX  1
PrintProcess.tcc
Go to the documentation of this file.
00001 #include "PrintAlgorithm.hpp"
00002 #include "PrintPlugin.hpp"
00003 
00004 #include <terry/channel.hpp>
00005 #include <terry/algorithm/pixel_by_channel.hpp>
00006 
00007 #include <cstdio>
00008 
00009 namespace tuttle {
00010 namespace plugin {
00011 namespace print {
00012 
00013 struct CacaImage
00014 {
00015         char *pixels;
00016         unsigned int w, h;
00017         caca_dither_t *dither;
00018 };
00019 
00020 template<class SView>
00021 CacaImage load_cacaimage_from_view( const SView sView )
00022 {
00023         typedef typename boost::gil::channel_mapping_type<SView>::type Channel;
00024         typedef typename terry::channel_base_type<Channel>::type ChannelBaseType;
00025 
00026         CacaImage im;
00027         unsigned int bpp, rmask, gmask, bmask, amask;
00028 
00029         im.pixels = (char*)boost::gil::interleaved_view_get_raw_data( sView );
00030         im.w = sView.width();
00031         im.h = sView.height();
00032         rmask = 0x000000ff;
00033         gmask = 0x0000ff00;
00034         bmask = 0x00ff0000;
00035         amask = 0x00000000;
00036         bpp = boost::gil::num_channels<SView>::value * sizeof( ChannelBaseType ) * 8;
00037 
00038         // Create the libcaca dither
00039         im.dither = caca_create_dither( bpp, im.w, im.h, sView.pixels().row_size(),
00040                                                                          rmask, gmask, bmask, amask);
00041 
00042         if( ! im.dither )
00043         {
00044                 BOOST_THROW_EXCEPTION( exception::Unknown() << exception::dev( "Unable to load buffer." ) );
00045         }
00046         return im;
00047 }
00048 
00049 template<>
00050 CacaImage load_cacaimage_from_view<boost::gil::gray8_view_t>( const boost::gil::gray8_view_t sView )
00051 {
00052         typedef boost::gil::channel_mapping_type<boost::gil::gray8_view_t>::type Channel;
00053         typedef terry::channel_base_type<Channel>::type ChannelBaseType;
00054 
00055         CacaImage im;
00056         unsigned int bpp, rmask, gmask, bmask, amask;
00057 
00058         im.pixels = (char*)boost::gil::interleaved_view_get_raw_data( sView );
00059         im.w = sView.width();
00060         im.h = sView.height();
00061         rmask = 0xff000000;
00062         gmask = 0x00ff0000;
00063         bmask = 0x0000ff00;
00064         amask = 0x00000000;
00065         bpp = boost::gil::num_channels<boost::gil::gray8_view_t>::value * sizeof( ChannelBaseType ) * 8;
00066 
00067         // Create the libcaca dither
00068         im.dither = caca_create_dither( bpp, im.w, im.h, sView.pixels().row_size(),
00069                                                                          rmask, gmask, bmask, amask);
00070 
00071         if( ! im.dither )
00072         {
00073                 BOOST_THROW_EXCEPTION( exception::Unknown() << exception::dev( "Unable to load buffer." ) );
00074         }
00075         return im;
00076 }
00077 
00078 template<typename Channel>
00079 struct channel_cout_t : public std::unary_function<Channel,Channel> {
00080         GIL_FORCEINLINE
00081         Channel operator()(typename boost::gil::channel_traits<Channel>::const_reference ch) const
00082         {
00083                 std::cout << ch << " ";
00084                 return ch;
00085         }
00086 };
00087 
00088 template<template<class> class Func>
00089 struct call_pixel_by_channel_t
00090 {
00091         template<typename Pixel>
00092         GIL_FORCEINLINE
00093         Pixel operator()( const Pixel& v ) const
00094         {
00095                 static_for_each( v, Func<typename boost::gil::channel_type<Pixel>::type>() );
00096                 return v;
00097         }
00098 };
00099 
00100 template<class View>
00101 PrintProcess<View>::PrintProcess( PrintPlugin &effect )
00102 : ImageGilFilterProcessor<View>( effect, eImageOrientationFromTopToBottom )
00103 , _plugin( effect )
00104 {
00105         this->setNoMultiThreading();
00106 }
00107 
00108 template<class View>
00109 PrintProcess<View>::~PrintProcess()
00110 {
00111 }
00112 
00113 template<class View>
00114 void PrintProcess<View>::setup( const OFX::RenderArguments& args )
00115 {
00116         ImageGilFilterProcessor<View>::setup( args );
00117         _params = _plugin.getProcessParams( args.renderScale );
00118 
00119 }
00120 
00121 /**
00122  * @brief Function called by rendering thread each time a process must be done.
00123  * @param[in] procWindowRoW  Processing window
00124  */
00125 template<class View>
00126 void PrintProcess<View>::multiThreadProcessImages( const OfxRectI& procWindowRoW )
00127 {
00128         using namespace boost::gil;
00129         //OfxRectI procWindowOutput = this->translateRoWToOutputClipCoordinates( procWindowRoW );
00130 
00131         const OfxRectI procWindowSrc = translateRegion( procWindowRoW, this->_srcPixelRod );
00132 
00133         View src = this->_srcView;
00134         View dst = this->_dstView;
00135 
00136         OfxRectI region = procWindowSrc;
00137 
00138         copy_pixels( src, dst );
00139 
00140         switch( _params._mode )
00141         {
00142                 case eParamModePixel:
00143                 {
00144                         call_pixel_by_channel_t<channel_cout_t>()( src( _params._pixel ) );
00145                         std::cout << std::endl;
00146                         break;
00147                 }
00148                 case eParamModeRegion:
00149                 {
00150                         src = subimage_view( this->_srcView, _params._region.x1, _params._region.y1,
00151                                                                                              _params._region.x2 - _params._region.x1,
00152                                                                                              _params._region.y2 - _params._region.y1 );
00153                         region = _params._region;
00154                         // continue with #src as a part of the image...
00155                 }
00156                 case eParamModeImage:
00157                 {
00158                         switch( _params._output )
00159                         {
00160                                 case eParamOutputNumeric:
00161                                 {
00162                                         std::cout << std::fixed;
00163                                         std::cout << std::setprecision( 2 );
00164                                         call_pixel_by_channel_t<channel_cout_t> proc;
00165                                         for( int y = region.y1; y < region.y2; ++y )
00166                                         {
00167                                                 std::cout << "| ";
00168                                                 typename View::x_iterator src_it = this->_srcView.x_at( region.x1, y );
00169                                                 for( int x = region.x1;
00170                                                          x < region.x2;
00171                                                          ++x, ++src_it )
00172                                                 {
00173                                                         proc( *src_it );
00174                                                         std::cout << " | ";
00175                                                 }
00176                                                 std::cout << "\n";
00177                                                 if( this->progressForward( region.x2 - region.x1 ) )
00178                                                         return;
00179                                         }
00180                                         break;
00181                                 }
00182                                 case eParamOutputAscii:
00183                                 {
00184                                         // temporary gray buffer to compute the char values.
00185                                         gray8_image_t gImgGray( src.dimensions() );
00186                                         gray8_view_t gViewGray( view(gImgGray) );
00187                                         rgb8_image_t gImg( src.dimensions() );
00188                                         rgb8_view_t gView( view(gImg) );
00189                                         
00190                                         if( _params._flip )
00191                                         {
00192                                                 src = flipped_up_down_view( src );
00193                                         }
00194 
00195                                         switch(_params._colorMode)
00196                                         {
00197                                                 case eParamColorMono :          copy_and_convert_pixels( src, gViewGray );      break;
00198                                                 case eParamColorGray :          copy_and_convert_pixels( src, gViewGray );      break;
00199                                                 default :                       copy_and_convert_pixels( src, gView );          break;
00200                                         }
00201                                         // libcaca context
00202                                         caca_canvas_t *cv = NULL;
00203 
00204                                         try
00205                                         {
00206                                                 struct CacaImage cacaImg;
00207                                                 unsigned int cols = 0, lines = 0, font_width = 6, font_height = 10;
00208                                                 char *dither = NULL;
00209                                                 float gamma = -1, brightness = -1, contrast = -1;
00210 
00211                                                 cv = caca_create_canvas(0, 0);
00212                                                 if( !cv )
00213                                                 {
00214                                                         BOOST_THROW_EXCEPTION( exception::Failed()
00215                                                                 << exception::user( "Print: unable to initialise libcaca" ) );
00216                                                 }
00217                                                 switch(_params._colorMode)
00218                                                 {
00219                                                         case eParamColorMono :          cacaImg = load_cacaimage_from_view( gViewGray );        break;
00220                                                         case eParamColorGray :          cacaImg = load_cacaimage_from_view( gViewGray );        break;
00221                                                         default :                       cacaImg = load_cacaimage_from_view( gView );            break;
00222                                                 }
00223 
00224                                                 /*
00225                                                  *  - \c "mono": use light gray on a black background.
00226                                                  *  - \c "gray": use white and two shades of gray on a black background.
00227                                                  *  - \c "8": use the 8 ANSI colours on a black background.
00228                                                  *  - \c "16": use the 16 ANSI colours on a black background.
00229                                                  *  - \c "fullgray": use black, white and two shades of gray for both the
00230                                                  *    characters and the background.
00231                                                  *  - \c "full8": use the 8 ANSI colours for both the characters and the
00232                                                  *    background.
00233                                                  *  - \c "full16" or \c "default": use the 16 ANSI colours for both the
00234                                                  *    characters and the background. This is the default value.
00235                                                  */
00236                                                 std::string colorMode;
00237                                                 switch(_params._colorMode)
00238                                                 {
00239                                                         case eParamColorMono :          colorMode = "mono";     break;
00240                                                         case eParamColorGray :          colorMode = "gray";     break;
00241                                                         case eParamColor8 :             colorMode = "8";        break;
00242                                                         case eParamColor16 :            colorMode = "16";       break;
00243                                                         case eParamColorfullgray :      colorMode = "fullgray"; break;
00244                                                         case eParamColorfull8 :         colorMode = "full8";    break;
00245                                                         case eParamColorfull16 :        colorMode = "full16";   break;
00246                                                 }
00247                                                 caca_set_dither_color( cacaImg.dither, colorMode.c_str() );
00248 
00249                                                 if( !cols && !lines )
00250                                                 {
00251                                                         cols = _params._cols + 1;
00252                                                         lines = cols * cacaImg.h * font_width / cacaImg.w / font_height;
00253                                                 }
00254                                                 else if( cols && !lines )
00255                                                 {
00256                                                         lines = cols * cacaImg.h * font_width / cacaImg.w / font_height;
00257                                                 }
00258                                                 else if( !cols && lines )
00259                                                 {
00260                                                         cols = lines * cacaImg.w * font_height / cacaImg.h / font_width;
00261                                                 }
00262                                                 //TUTTLE_LOG_TRACE( "output : " << cols << " x " << lines );
00263                                                 caca_set_canvas_size( cv, cols, lines );
00264 
00265                                                 caca_clear_canvas( cv );
00266 
00267                                                 if( caca_set_dither_algorithm( cacaImg.dither, dither?dither:"fstein" ) )
00268                                                 {
00269                                                         BOOST_THROW_EXCEPTION( exception::Unknown()
00270                                                         << exception::dev() + "Can't dither image with algorithm " + dither );
00271                                                 }
00272 
00273                                                 if( brightness != -1 )
00274                                                         caca_set_dither_brightness( cacaImg.dither, brightness );
00275                                                 if( contrast != -1 )
00276                                                         caca_set_dither_contrast( cacaImg.dither, contrast );
00277                                                 if( gamma != -1 )
00278                                                         caca_set_dither_gamma( cacaImg.dither, gamma );
00279 
00280                                                 caca_dither_bitmap( cv, 0, 0, cols, lines, cacaImg.dither, cacaImg.pixels );
00281 
00282                                                 caca_free_dither( cacaImg.dither );
00283 
00284 
00285                                                 if( _params._openGlViewer == true )
00286                                                 {
00287                                                         // show result in a new window
00288                                                         caca_display_t *dp;
00289                                                         caca_event_t ev;
00290                                                         dp = caca_create_display (cv);
00291 
00292                                                         caca_set_display_title(dp, "Rendering image in ASCII Art");
00293 
00294                                                         caca_refresh_display(dp);
00295                                                         caca_get_event(dp, CACA_EVENT_KEY_PRESS | CACA_EVENT_QUIT |CACA_EVENT_MOUSE_RELEASE, &ev, -1);
00296                                                         caca_free_display(dp);
00297 
00298                                                         caca_free_canvas( cv );
00299                                                 }
00300                                                 else
00301                                                 {
00302                                                         //clear the sreen
00303                                                         std::cout << std::string( 100, '\n' );
00304 
00305                                                         size_t len;
00306                                                         void *output;
00307 
00308                                                         output = caca_export_canvas_to_memory( cv, "ansi", &len );
00309                                                         fwrite( output, len, 1, stdout );
00310                                                         free( output );
00311 
00312                                                         caca_free_canvas( cv );
00313                                                 }
00314                                         }
00315                                         catch(...)
00316                                         {
00317                                                 TUTTLE_LOG_CURRENT_EXCEPTION;
00318                                                 if(cv != NULL )
00319                                                 caca_free_canvas( cv );
00320                                         }
00321                                         break;
00322                                 }
00323                         }
00324                         break;
00325                 }
00326         }
00327 }
00328 
00329 
00330 }
00331 }
00332 }