Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

image_filters.cc

Go to the documentation of this file.
00001 /*
00002 * image_filters.cc -- RGB24 image filters
00003 * Copyright (C) 2002 Charles Yates <charles.yates@pandora.be>
00004 * Copyright (C) 2002-2007 Dan Dennedy <dan@dennedy.org>
00005 *
00006 * This program is free software; you can redistribute it and/or modify
00007 * it under the terms of the GNU General Public License as published by
00008 * the Free Software Foundation; either version 2 of the License, or
00009 * (at your option) any later version.
00010 *
00011 * This program is distributed in the hope that it will be useful,
00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 * GNU General Public License for more details.
00015 *
00016 * You should have received a copy of the GNU General Public License
00017 * along with this program; if not, write to the Free Software Foundation,
00018 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00019 */
00020 
00021 #ifdef HAVE_CONFIG_H
00022 #include <config.h>
00023 #endif
00024 
00025 #include <iostream>
00026 
00027 // Project Includes
00028 
00029 #include "image_filters.h"
00030 #include "error.h"
00031 #include "page_magick.h"
00032 #include "kino_extra.h"
00033 
00034 // C Includes
00035 
00036 #include <string.h>
00037 #include <stdio.h>
00038 #include <glade/glade.h>
00039 
00040 extern "C"
00041 {
00042 #include "support.h"
00043     extern GladeXML* magick_glade;
00044 }
00045 
00049 class ImageFilterKeep : public GDKImageFilter, public NullImageFilter
00050 {
00051 public:
00052     char *GetDescription( ) const
00053     {
00054         return _( "No Change" );
00055     }
00056 
00057     void FilterFrame( uint8_t *pixels, int width, int height, double position, double frame_delta )
00058     {}
00059 }
00060 ;
00061 
00065 class ImageFilterBlackWhite : public ImageFilter
00066 {
00067 public:
00068     char *GetDescription( ) const
00069     {
00070         return _( "Black & White" );
00071     }
00072 
00073     void FilterFrame( uint8_t *pixels, int width, int height, double position, double frame_delta )
00074     {
00075         uint8_t r, g, b;
00076         uint8_t *p = pixels;
00077         while ( p < ( pixels + width * height * 3 ) )
00078         {
00079             r = *( p );
00080             g = *( p + 1 );
00081             b = *( p + 2 );
00082             r = ( uint8_t ) ( 0.299 * r + 0.587 * g + 0.114 * b );
00083             *p ++ = r;
00084             *p ++ = r;
00085             *p ++ = r;
00086         }
00087     }
00088 };
00089 
00093 class ImageFilterFadeIn : public ImageFilter
00094 {
00095 public:
00096     char *GetDescription( ) const
00097     {
00098         return _( "Fade In" );
00099     }
00100 
00101     void FilterFrame( uint8_t *pixels, int width, int height, double position, double frame_delta )
00102     {
00103         for ( uint8_t *p = pixels; p < ( pixels + width * height * 3 ); ++p )
00104             *p = uint8_t( *p * position + 0.5 );
00105     }
00106 };
00107 
00111 class ImageFilterFadeOut : public ImageFilter
00112 {
00113 public:
00114     char *GetDescription( ) const
00115     {
00116         return _( "Fade Out" );
00117     }
00118 
00119     void FilterFrame( uint8_t *pixels, int width, int height, double position, double frame_delta )
00120     {
00121         double r = ( 1.0 - position );
00122         for ( uint8_t *p = pixels; p < ( pixels + width * height * 3 ); ++p )
00123             *p = uint8_t( *p * r + 0.5 );
00124     }
00125 };
00126 
00130 class ImageFilterSepia : public ImageFilter
00131 {
00132 public:
00133     char *GetDescription( ) const
00134     {
00135         return _( "Sepia" );
00136     }
00137 
00138     void FilterFrame( uint8_t *pixels, int width, int height, double position, double frame_delta )
00139     {
00140         uint8_t r, g, b;
00141         uint8_t *p = pixels;
00142         while ( p < ( pixels + width * height * 3 ) )
00143         {
00144             r = *( p );
00145             g = *( p + 1 );
00146             b = *( p + 2 );
00147             r = ( uint8_t ) ( 0.299 * r + 0.587 * g + 0.114 * b );
00148             *p ++ = r < 225 ? ( int ) ( r + 30 ) : 0xff;
00149             *p ++ = r;
00150             *p ++ = r > 30 ? ( int ) ( r - 30 ) : 0;
00151         }
00152     }
00153 };
00154 
00158 class ImageFilterMirror : public GDKImageFilter
00159 {
00160 private:
00161     GtkWidget *window;
00162     int type;
00163 
00164 public:
00165     ImageFilterMirror()
00166     {
00167         window = glade_xml_get_widget( magick_glade, "image_filter_mirror" );
00168         GtkWidget* widget = glade_xml_get_widget( magick_glade, "optionmenu_mirror" );
00169         g_signal_connect( G_OBJECT( widget ), "changed", G_CALLBACK( Repaint ), 0 );
00170     }
00171 
00172     virtual ~ImageFilterMirror()
00173     {
00174         gtk_widget_destroy( window );
00175     }
00176 
00177     char *GetDescription( ) const
00178     {
00179         return _( "Mirror" );
00180     }
00181 
00182     void LeftRight( uint8_t *pixels, int width, int height, double position )
00183     {
00184         uint8_t * p = pixels;
00185         for ( int y = 0; y < height; y ++ )
00186         {
00187             uint8_t *i = p + y * width * 3;
00188             uint8_t *o = p + ( y + 1 ) * width * 3 - 1;
00189             for ( ; o > i; o -= 3 )
00190             {
00191                 *( o - 2 ) = *i ++;
00192                 *( o - 1 ) = *i ++;
00193                 *o = *i ++;
00194             }
00195         }
00196     }
00197 
00198     void RightLeft( uint8_t *pixels, int width, int height, double position )
00199     {
00200         uint8_t * p = pixels;
00201         for ( int y = 0; y < height; y ++ )
00202         {
00203             uint8_t *o = p + y * width * 3;
00204             uint8_t *i = p + ( y + 1 ) * width * 3 - 1;
00205             for ( ; i > o; i -= 3 )
00206             {
00207                 *o ++ = *( i - 2 );
00208                 *o ++ = *( i - 1 );
00209                 *o ++ = *i;
00210             }
00211         }
00212     }
00213 
00214     void TopBottom( uint8_t *pixels, int width, int height, double position )
00215     {
00216         uint8_t * p = pixels;
00217         for ( int y = 0; y < height / 2; y ++ )
00218         {
00219             uint8_t *i = p + y * width * 3;
00220             uint8_t *o = p + ( height - y ) * width * 3;
00221             memcpy( o, i, width * 3 );
00222         }
00223     }
00224 
00225     void BottomTop( uint8_t *pixels, int width, int height, double position )
00226     {
00227         uint8_t * p = pixels;
00228         for ( int y = 0; y < height / 2; y ++ )
00229         {
00230             uint8_t *i = p + ( height - y ) * width * 3;
00231             uint8_t *o = p + y * width * 3;
00232             memcpy( o, i, width * 3 );
00233         }
00234     }
00235 
00236     void FilterFrame( uint8_t *pixels, int width, int height, double position, double frame_delta )
00237     {
00238         GtkMenu * menu = GTK_MENU( gtk_option_menu_get_menu( GTK_OPTION_MENU( lookup_widget( window, "optionmenu_mirror" ) ) ) );
00239         GtkWidget *active_item = gtk_menu_get_active( menu );
00240         type = g_list_index ( GTK_MENU_SHELL ( menu ) ->children, active_item );
00241         
00242         if ( type == 0 )
00243             LeftRight( pixels, width, height, position );
00244         else if ( type == 1 )
00245             RightLeft( pixels, width, height, position );
00246         else if ( type == 2 )
00247             TopBottom( pixels, width, height, position );
00248         else if ( type == 3 )
00249             BottomTop( pixels, width, height, position );
00250     }
00251 
00252     void AttachWidgets( GtkBin *bin )
00253     {
00254         gtk_widget_reparent( ( GTK_BIN( window ) ) ->child, GTK_WIDGET( bin ) );
00255     }
00256 
00257     void DetachWidgets( GtkBin *bin )
00258     {
00259         gtk_widget_reparent( ( GTK_BIN( bin ) ) ->child, GTK_WIDGET( window ) );
00260     }
00261 };
00262 
00266 class ImageFilterKaleidoscope: public GDKImageFilter
00267 {
00268 private:
00269     GtkWidget *window;
00270     int type;
00271 
00272 public:
00273     ImageFilterKaleidoscope()
00274     {
00275         window = glade_xml_get_widget( magick_glade, "image_filter_kaleidoscope" );
00276         GtkWidget* widget = glade_xml_get_widget( magick_glade, "optionmenu_kaleidoscope" );
00277         g_signal_connect( G_OBJECT( widget ), "changed", G_CALLBACK( Repaint ), 0 );
00278     }
00279 
00280     virtual ~ImageFilterKaleidoscope()
00281     {
00282         gtk_widget_destroy( window );
00283     }
00284 
00285     char *GetDescription( ) const
00286     {
00287         return _( "Kaleidoscope" );
00288     }
00289 
00290     void TopLeft( uint8_t *pixels, int width, int height, double position )
00291     {
00292         uint8_t r, g, b;
00293         uint8_t *p = pixels;
00294         for ( int y = 0; y <= height / 2; y ++ )
00295         {
00296             uint8_t *i = p + y * width * 3;
00297             uint8_t *o = p + ( y + 1 ) * width * 3 - 1;
00298             uint8_t *o1 = p + ( height - y ) * width * 3;
00299             uint8_t *o2 = p + ( height - y + 1 ) * width * 3 - 1;
00300             while ( o > i )
00301             {
00302                 r = *i ++;
00303                 g = *i ++;
00304                 b = *i ++;
00305                 *o -- = b;
00306                 *o -- = g;
00307                 *o -- = r;
00308                 *o1 ++ = r;
00309                 *o1 ++ = g;
00310                 *o1 ++ = b;
00311                 *o2 -- = b;
00312                 *o2 -- = g;
00313                 *o2 -- = r;
00314             }
00315         }
00316     }
00317 
00318     void TopRight( uint8_t *pixels, int width, int height, double position )
00319     {
00320         uint8_t r, g, b;
00321         uint8_t *p = pixels;
00322         for ( int y = 0; y <= height / 2; y ++ )
00323         {
00324             uint8_t *i = p + ( y + 1 ) * width * 3 - 1;
00325             uint8_t *o = p + y * width * 3;
00326             uint8_t *o1 = p + ( height - y ) * width * 3;
00327             uint8_t *o2 = p + ( height - y + 1 ) * width * 3 - 1;
00328             while ( i > o )
00329             {
00330                 b = *i --;
00331                 g = *i --;
00332                 r = *i --;
00333                 *o ++ = r;
00334                 *o ++ = g;
00335                 *o ++ = b;
00336                 *o1 ++ = r;
00337                 *o1 ++ = g;
00338                 *o1 ++ = b;
00339                 *o2 -- = b;
00340                 *o2 -- = g;
00341                 *o2 -- = r;
00342             }
00343         }
00344     }
00345 
00346     void BottomLeft( uint8_t *pixels, int width, int height, double position )
00347     {
00348         uint8_t r, g, b;
00349         uint8_t *p = pixels;
00350         for ( int y = 0; y <= height / 2; y ++ )
00351         {
00352             uint8_t *o1 = p + y * width * 3;
00353             uint8_t *o2 = p + ( y + 1 ) * width * 3 - 1;
00354             uint8_t *i = p + ( height - y ) * width * 3;
00355             uint8_t *o = p + ( height - y + 1 ) * width * 3 - 1;
00356             while ( o > i )
00357             {
00358                 r = *i ++;
00359                 g = *i ++;
00360                 b = *i ++;
00361                 *o -- = b;
00362                 *o -- = g;
00363                 *o -- = r;
00364                 *o1 ++ = r;
00365                 *o1 ++ = g;
00366                 *o1 ++ = b;
00367                 *o2 -- = b;
00368                 *o2 -- = g;
00369                 *o2 -- = r;
00370             }
00371         }
00372     }
00373 
00374     void BottomRight( uint8_t *pixels, int width, int height, double position )
00375     {
00376         uint8_t r, g, b;
00377         uint8_t *p = pixels;
00378         for ( int y = 0; y <= height / 2; y ++ )
00379         {
00380             uint8_t *o2 = p + ( y + 1 ) * width * 3 - 1;
00381             uint8_t *o1 = p + y * width * 3;
00382             uint8_t *o = p + ( height - y ) * width * 3;
00383             uint8_t *i = p + ( height - y + 1 ) * width * 3 - 1;
00384             while ( i > o )
00385             {
00386                 b = *i --;
00387                 g = *i --;
00388                 r = *i --;
00389                 *o ++ = r;
00390                 *o ++ = g;
00391                 *o ++ = b;
00392                 *o1 ++ = r;
00393                 *o1 ++ = g;
00394                 *o1 ++ = b;
00395                 *o2 -- = b;
00396                 *o2 -- = g;
00397                 *o2 -- = r;
00398             }
00399         }
00400     }
00401 
00402     void FilterFrame( uint8_t *pixels, int width, int height, double position, double frame_delta )
00403     {
00404         GtkMenu * menu = GTK_MENU( gtk_option_menu_get_menu( GTK_OPTION_MENU( lookup_widget( window, "optionmenu_kaleidoscope" ) ) ) );
00405         GtkWidget *active_item = gtk_menu_get_active( menu );
00406         type = g_list_index ( GTK_MENU_SHELL ( menu ) ->children, active_item );
00407         
00408         if ( type == 0 )
00409             TopLeft( pixels, width, height, position );
00410         else if ( type == 1 )
00411             TopRight( pixels, width, height, position );
00412         else if ( type == 2 )
00413             BottomLeft( pixels, width, height, position );
00414         else if ( type == 3 )
00415             BottomRight( pixels, width, height, position );
00416     }
00417 
00418     void AttachWidgets( GtkBin *bin )
00419     {
00420         gtk_widget_reparent( ( GTK_BIN( window ) ) ->child, GTK_WIDGET( bin ) );
00421     }
00422 
00423     void DetachWidgets( GtkBin *bin )
00424     {
00425         gtk_widget_reparent( ( GTK_BIN( bin ) ) ->child, GTK_WIDGET( window ) );
00426     }
00427 };
00428 
00432 class ImageFilterReverseVideo : public ImageFilter
00433 {
00434 public:
00435     char *GetDescription( ) const
00436     {
00437         return _( "Reverse Video" );
00438     }
00439 
00440     void FilterFrame( uint8_t *pixels, int width, int height, double position, double frame_delta )
00441     {
00442         uint8_t r, g, b;
00443         uint8_t *p = pixels;
00444         while ( p < ( pixels + width * height * 3 ) )
00445         {
00446             r = *( p );
00447             g = *( p + 1 );
00448             b = *( p + 2 );
00449             *p ++ = 0xff - r;
00450             *p ++ = 0xff - g;
00451             *p ++ = 0xff - b;
00452         }
00453     }
00454 };
00455 
00459 class ImageFilterSwap : public GDKImageFilter
00460 {
00461 private:
00462     GtkWidget *window;
00463     int type;
00464 
00465 public:
00466     ImageFilterSwap()
00467     {
00468         window = glade_xml_get_widget( magick_glade, "image_filter_swap" );
00469         GtkWidget* widget = glade_xml_get_widget( magick_glade, "optionmenu_swap" );
00470         g_signal_connect( G_OBJECT( widget ), "changed", G_CALLBACK( Repaint ), 0 );
00471     }
00472 
00473     virtual ~ImageFilterSwap()
00474     {
00475         gtk_widget_destroy( window );
00476     }
00477 
00478     char *GetDescription( ) const
00479     {
00480         return _( "Flip" );
00481     }
00482 
00483     void LeftRight( uint8_t *pixels, int width, int height, double position )
00484     {
00485         uint8_t r, g, b;
00486         uint8_t *p = pixels;
00487         for ( int y = 0; y < height; y ++ )
00488         {
00489             uint8_t *i = p + y * width * 3;
00490             uint8_t *o = p + ( y + 1 ) * width * 3 - 1;
00491             for ( int x = 0; x < width / 2; x ++ )
00492             {
00493                 r = *i;
00494                 g = *( i + 1 );
00495                 b = *( i + 2 );
00496                 *i ++ = *( o - 2 );
00497                 *i ++ = *( o - 1 );
00498                 *i ++ = *o;
00499                 *o -- = b;
00500                 *o -- = g;
00501                 *o -- = r;
00502             }
00503         }
00504     }
00505 
00506     void TopBottom( uint8_t *pixels, int width, int height, double position )
00507     {
00508         uint8_t * p = pixels;
00509         uint8_t keyFrame[ 720 * 3 ];
00510         for ( int y = 0; y < height / 2; y ++ )
00511         {
00512             uint8_t *i = p + y * width * 3;
00513             uint8_t *o = p + ( height - y - 1 ) * width * 3;
00514             memcpy( keyFrame, i, width * 3 );
00515             memcpy( i, o, width * 3 );
00516             memcpy( o, keyFrame, width * 3 );
00517         }
00518     }
00519 
00520     void FilterFrame( uint8_t *pixels, int width, int height, double position, double frame_delta )
00521     {
00522         GtkMenu * menu = GTK_MENU( gtk_option_menu_get_menu( GTK_OPTION_MENU( lookup_widget( window, "optionmenu_swap" ) ) ) );
00523         GtkWidget *active_item = gtk_menu_get_active( menu );
00524         type = g_list_index ( GTK_MENU_SHELL ( menu ) ->children, active_item );
00525         
00526         if ( type == 0 )
00527             LeftRight( pixels, width, height, position );
00528         else if ( type == 1 )
00529             TopBottom( pixels, width, height, position );
00530     }
00531 
00532     void AttachWidgets( GtkBin *bin )
00533     {
00534         gtk_widget_reparent( ( GTK_BIN( window ) ) ->child, GTK_WIDGET( bin ) );
00535     }
00536 
00537     void DetachWidgets( GtkBin *bin )
00538     {
00539         gtk_widget_reparent( ( GTK_BIN( bin ) ) ->child, GTK_WIDGET( window ) );
00540     }
00541 };
00542 
00546 static void
00547 on_optionmenu_selected ( GtkMenuItem *menu_item, gpointer user_data )
00548 {
00549     ( ( GDKImageFilterRepository * ) user_data ) ->SelectionChange();
00550 }
00551 
00557 GDKImageFilterRepository::GDKImageFilterRepository()
00558     : selected_filter( 0 )
00559 {
00560     // Register an instance of each object (adapting raw filters to GDK filters where necessary)
00561     Register( new ImageFilterKeep() );
00562     Register( new GDKImageFilterAdapter( new ImageFilterBlackWhite() ) );
00563     Register( new ImageFilterKaleidoscope() );
00564     Register( new GDKImageFilterAdapter( new ImageFilterFadeIn() ) );
00565     Register( new GDKImageFilterAdapter( new ImageFilterFadeOut() ) );
00566     Register( new ImageFilterSwap() );
00567     Register( new ImageFilterMirror() );
00568     Register( new GDKImageFilterAdapter( new ImageFilterReverseVideo() ) );
00569     Register( new GDKImageFilterAdapter( new ImageFilterSepia() ) );
00570 }
00571 
00575 GDKImageFilterRepository::~GDKImageFilterRepository()
00576 {
00577     // Remove the filters in the repository
00578     for ( unsigned int index = 0; index < filters.size(); index ++ )
00579         delete filters[ index ];
00580 }
00581 
00585 void GDKImageFilterRepository::Register( GDKImageFilter *filter )
00586 {
00587     std::cerr << ">>> Image Filter: " << filter->GetDescription( ) << std::endl;
00588     filters.push_back( filter );
00589 }
00590 
00594 void GDKImageFilterRepository::Initialise( GtkOptionMenu *menu, GtkBin *container )
00595 {
00596     // Store these for future reference
00597     this->menu = menu;
00598     this->container = container;
00599 
00600     // Add the filters to the menu
00601     GtkMenu *menu_new = GTK_MENU( gtk_menu_new( ) );
00602     for ( unsigned int index = 0; index < filters.size(); index ++ )
00603     {
00604         GtkWidget *item = gtk_menu_item_new_with_label( filters[ index ] ->GetDescription( ) );
00605         gtk_widget_show( item );
00606         gtk_menu_append( menu_new, item );
00607         g_signal_connect( G_OBJECT( item ), "activate", G_CALLBACK( on_optionmenu_selected ), this );
00608     }
00609     gtk_menu_set_active( menu_new, 0 );
00610     gtk_option_menu_set_menu( menu, GTK_WIDGET( menu_new ) );
00611 
00612     // Register the selected items widgets
00613     SelectionChange();
00614 }
00615 
00619 GDKImageFilter *GDKImageFilterRepository::Get( ) const
00620 {
00621     GtkMenu * filterMenu = GTK_MENU( gtk_option_menu_get_menu( menu ) );
00622     GtkWidget *active_item = gtk_menu_get_active( filterMenu );
00623     return filters[ g_list_index( GTK_MENU_SHELL( filterMenu ) ->children, active_item ) ];
00624 }
00625 
00629 void GDKImageFilterRepository::SelectionChange( )
00630 {
00631     bool isPreviewing = false;
00632     PageMagick* magick = 0;
00633 
00634     if ( common && common->getPageMagick( ) )
00635         magick = common->getPageMagick( );
00636     if ( magick && magick->IsPreviewing() )
00637     {
00638         isPreviewing = true;
00639         magick->StopPreview();
00640     }
00641 
00642     // Detach the selected filters widgets
00643     if ( selected_filter != NULL )
00644         selected_filter->DetachWidgets( container );
00645 
00646     if ( magick )
00647     {
00648         magick->SetKeyFrameControllerClient(0);
00649         magick->ShowCurrentStatus( magick->GetCurrentPosition(), LOCKED_KEY, false, false );
00650     }
00651 
00652     // Get the new selection
00653     selected_filter = Get();
00654 
00655     // Attach the new filters widgets
00656     if ( selected_filter != NULL )
00657         selected_filter->AttachWidgets( container );
00658 
00659     if ( magick )
00660     {
00661         if ( isPreviewing )
00662             magick->StartPreview();
00663         else
00664             magick->PreviewFrame();
00665     }
00666 }

Generated on Sun Mar 11 22:11:45 2007 for Kino by  doxygen 1.4.2