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

image_transitions.cc

Go to the documentation of this file.
00001 /*
00002 * image_transitions.cc -- RGB24 image transitions
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_transitions.h"
00030 #include "page_magick.h"
00031 #include "kino_extra.h"
00032 
00033 // C Includes
00034 
00035 #include <string.h>
00036 #include <stdio.h>
00037 #include <glade/glade.h>
00038 
00039 extern "C"
00040 {
00041 #include "support.h"
00042     extern GladeXML* magick_glade;
00043 }
00044 
00045 class ImageTransitionNone : public GDKImageTransition
00046 {
00047     char *GetDescription( ) const
00048     {
00049         return _( "No Change" );
00050     }
00051     
00052     void GetFrame( uint8_t *pixels, uint8_t *mesh, int width, int height, double position, double frame_delta, bool reverse )
00053     {
00054     }
00055 };
00056 
00057 class ImageTransitionSwitch : public GDKImageTransition
00058 {
00059 private:
00060     GtkWidget *window;
00061     double point;
00062 
00063 public:
00064     ImageTransitionSwitch()
00065     {
00066         window = glade_xml_get_widget( magick_glade, "image_transition_switch" );
00067         GtkWidget* widget = lookup_widget( window, "hscale_switch" );
00068         g_signal_connect( G_OBJECT( widget ), "value-changed", G_CALLBACK( Repaint ), 0 );
00069     }
00070 
00071     virtual ~ImageTransitionSwitch()
00072     {
00073         gtk_widget_destroy( window );
00074     }
00075 
00076     char *GetDescription( ) const
00077     {
00078         return _( "Switch" );
00079     }
00080 
00081     void GetFrame( uint8_t *pixels, uint8_t *mesh, int width, int height, double position, double frame_delta, bool reverse )
00082     {
00083         GtkRange * range = GTK_RANGE( lookup_widget( window, "hscale_switch" ) );
00084         GtkAdjustment *adjust = gtk_range_get_adjustment( range );
00085         point = adjust->value / 100;
00086         
00087         if ( position >= point )
00088             memcpy( pixels, mesh, width * height * 3 );
00089     }
00090 
00091     void AttachWidgets( GtkBin *bin )
00092     {
00093         gtk_widget_reparent( ( GTK_BIN( window ) ) ->child, GTK_WIDGET( bin ) );
00094     }
00095 
00096     void DetachWidgets( GtkBin *bin )
00097     {
00098         gtk_widget_reparent( ( GTK_BIN( bin ) ) ->child, GTK_WIDGET( window ) );
00099     }
00100 
00101     double SwitchPoint( )
00102     {
00103         return point;
00104     }
00105 };
00106 
00110 class ImageTransitionFade : public GDKImageTransition
00111 {
00112 public:
00113     char *GetDescription( ) const
00114     {
00115         return _( "Dissolve" );
00116     }
00117 
00118     void GetFrame( uint8_t *io, uint8_t *mesh, int width, int height, double position, double frame_delta, bool reverse )
00119     {
00120         uint8_t * k = mesh;
00121         uint8_t *p = io;
00122         uint8_t r, g, b;
00123         uint8_t kr, kg, kb;
00124 
00125         if ( reverse )
00126             position = 1 - position;
00127 
00128         while ( p < ( io + width * height * 3 ) )
00129         {
00130             r = *p;
00131             g = *( p + 1 );
00132             b = *( p + 2 );
00133             kr = *k ++;
00134             kg = *k ++;
00135             kb = *k ++;
00136             int vr = ( int ) ( kr * position + r * ( 1 - position ) );
00137             int vg = ( int ) ( kg * position + g * ( 1 - position ) );
00138             int vb = ( int ) ( kb * position + b * ( 1 - position ) );
00139             *p ++ = vr < 0xff ? ( uint8_t ) vr : 0xff;
00140             *p ++ = vg < 0xff ? ( uint8_t ) vg : 0xff;
00141             *p ++ = vb < 0xff ? ( uint8_t ) vb : 0xff;
00142         }
00143     }
00144 };
00145 
00149 class ImageTransitionBarWipe : public GDKImageTransition
00150 {
00151 private:
00152     GtkWidget *window;
00153     int type;
00154 
00155 public:
00156     ImageTransitionBarWipe()
00157     {
00158         window = glade_xml_get_widget( magick_glade, "image_transition_bar_wipe" );
00159         GtkWidget* widget = lookup_widget( window, "optionmenu_wipe" );
00160         g_signal_connect( G_OBJECT( widget ), "changed", G_CALLBACK( Repaint ), 0 );
00161     }
00162 
00163     virtual ~ImageTransitionBarWipe()
00164     {
00165         gtk_widget_destroy( window );
00166     }
00167 
00168     char *GetDescription( ) const
00169     {
00170         return _( "Push Wipe" );
00171     }
00172 
00173     void Left( uint8_t *io, uint8_t *mesh, int width, int height, double position )
00174     {
00175         int roll_width = ( int ) ( width * position );
00176         for ( int y = 0; y < height; y ++ )
00177         {
00178             uint8_t *k = mesh + y * width * 3;
00179             uint8_t *p = io + y * width * 3;
00180             memmove( p, p + roll_width * 3, ( width * 3 ) - roll_width * 3 );
00181             p = io + ( ( y + 1 ) * width * 3 ) - roll_width * 3;
00182             memcpy( p, k, roll_width * 3 );
00183         }
00184     }
00185 
00186     void Right( uint8_t *io, uint8_t *mesh, int width, int height, double position )
00187     {
00188         uint8_t temp[ 720 * 3 ];
00189         int roll_width = ( int ) ( width * position );
00190         for ( int y = 0; y < height; y ++ )
00191         {
00192             uint8_t *k = mesh + y * width * 3;
00193             uint8_t *p = io + y * width * 3;
00194             memcpy( temp, k + ( width - roll_width ) * 3, roll_width * 3 );
00195             memcpy( temp + roll_width * 3, p, ( width * 3 ) - roll_width * 3 );
00196             memcpy( p, temp, width * 3 );
00197         }
00198     }
00199 
00200     void Down( uint8_t *io, uint8_t *mesh, int width, int height, double position )
00201     {
00202         int roll_height = ( int ) ( height * position );
00203         memmove( io + roll_height * width * 3, io, ( height - roll_height ) * width * 3 );
00204         for ( int y = 0; y < roll_height; y ++ )
00205         {
00206             uint8_t *p = io + y * width * 3;
00207             uint8_t *k = mesh + ( y + height - roll_height ) * width * 3;
00208             memcpy( p, k, width * 3 );
00209         }
00210     }
00211 
00212     void Up( uint8_t *io, uint8_t *mesh, int width, int height, double position )
00213     {
00214         int roll_height = ( int ) ( height * ( 1 - position ) );
00215         memmove( io, io + ( height - roll_height ) * width * 3, roll_height * width * 3 );
00216         for ( int y = roll_height; y < height; y ++ )
00217         {
00218             uint8_t *p = io + y * width * 3;
00219             uint8_t *k = mesh + ( y - roll_height ) * width * 3;
00220             memcpy( p, k, width * 3 );
00221         }
00222     }
00223 
00224     void GetFrame( uint8_t *pixels, uint8_t *mesh, int width, int height, double position, double frame_delta, bool reverse )
00225     {
00226         GtkMenu * menu = GTK_MENU( gtk_option_menu_get_menu( GTK_OPTION_MENU( lookup_widget( window, "optionmenu_wipe" ) ) ) );
00227         GtkWidget *active_item = gtk_menu_get_active( menu );
00228         type = g_list_index ( GTK_MENU_SHELL ( menu ) ->children, active_item );
00229         
00230         if ( type == 0 && !reverse )
00231             Left( pixels, mesh, width, height, position );
00232         else if ( type == 0 && reverse )
00233             Right( pixels, mesh, width, height, position );
00234         else if ( type == 1 && !reverse )
00235             Down( pixels, mesh, width, height, position );
00236         else if ( type == 1 && reverse )
00237             Up( pixels, mesh, width, height, position );
00238     }
00239 
00240     void AttachWidgets( GtkBin *bin )
00241     {
00242         gtk_widget_reparent( ( GTK_BIN( window ) ) ->child, GTK_WIDGET( bin ) );
00243     }
00244 
00245     void DetachWidgets( GtkBin *bin )
00246     {
00247         gtk_widget_reparent( ( GTK_BIN( bin ) ) ->child, GTK_WIDGET( window ) );
00248     }
00249 };
00250 
00254 #define DIFFERS_BY( w, v, o )   ( abs( v - w ) < o )
00255 
00256 class ImageTransitionDifferences : public GDKImageTransition
00257 {
00258 private:
00259     GtkWidget *window;
00260     int type;
00261     int sensitivity;
00262     GdkColor color;
00263 
00264 public:
00265     ImageTransitionDifferences()
00266     {
00267         window = glade_xml_get_widget( magick_glade, "image_transition_differences" );
00268         GtkWidget* widget = lookup_widget( window, "optionmenu_action" );
00269         g_signal_connect( G_OBJECT( widget ), "changed", G_CALLBACK( Repaint ), 0 );
00270         widget = lookup_widget( window, "colorpicker" );
00271         g_signal_connect( G_OBJECT( widget ), "color-set", G_CALLBACK( Repaint ), 0 );
00272         widget = lookup_widget( window, "hscale_sensitivity" );
00273         g_signal_connect( G_OBJECT( widget ), "value-changed", G_CALLBACK( Repaint ), 0 );
00274     }
00275 
00276     virtual ~ImageTransitionDifferences()
00277     {
00278         gtk_widget_destroy( window );
00279     }
00280 
00281     char *GetDescription( ) const
00282     {
00283         return _( "Differences" );
00284     }
00285 
00286     void GetFrame( uint8_t *io, uint8_t *mesh, int width, int height, double position, double frame_delta, bool reverse )
00287     {
00288         GtkMenu *menu = GTK_MENU( gtk_option_menu_get_menu( GTK_OPTION_MENU( lookup_widget( window, "optionmenu_action" ) ) ) );
00289         GtkWidget *active_item = gtk_menu_get_active( menu );
00290         type = g_list_index ( GTK_MENU_SHELL ( menu ) ->children, active_item );
00291 
00292         GtkColorButton *colorButton = GTK_COLOR_BUTTON( lookup_widget( window, "colorpicker" ) );
00293         gtk_color_button_get_color( colorButton, &color );
00294 
00295         GtkRange *range = GTK_RANGE( lookup_widget( window, "hscale_sensitivity" ) );
00296         GtkAdjustment *adjust = gtk_range_get_adjustment( range );
00297         sensitivity = ( int ) adjust->value;
00298         
00299         // Differences only
00300         uint8_t * k = mesh;
00301         uint8_t *p = io;
00302         uint8_t r, g, b;
00303         uint8_t kr, kg, kb;
00304         for ( int y = 0; y < height; y ++ )
00305         {
00306             for ( int x = 0; x < width; x ++ )
00307             {
00308                 r = *p;
00309                 g = *( p + 1 );
00310                 b = *( p + 2 );
00311                 kr = *k ++;
00312                 kg = *k ++;
00313                 kb = *k ++;
00314 
00315                 bool differs = DIFFERS_BY( kr, r, sensitivity ) && DIFFERS_BY( kg, g, sensitivity ) && DIFFERS_BY( kb, b, sensitivity );
00316 
00317                 if ( ( !differs && type == 0 ) || ( differs && type == 1 ) )
00318                 {
00319                     *p ++ = color.red >> 8;
00320                     *p ++ = color.green >> 8;
00321                     *p ++ = color.blue >> 8;
00322                 }
00323                 else
00324                 {
00325                     *p ++ = r;
00326                     *p ++ = g;
00327                     *p ++ = b;
00328                 }
00329             }
00330         }
00331     }
00332 
00333     void AttachWidgets( GtkBin *bin )
00334     {
00335         gtk_widget_reparent( ( GTK_BIN( window ) ) ->child, GTK_WIDGET( bin ) );
00336     }
00337 
00338     void DetachWidgets( GtkBin *bin )
00339     {
00340         gtk_widget_reparent( ( GTK_BIN( bin ) ) ->child, GTK_WIDGET( window ) );
00341     }
00342 };
00343 
00347 class ImageTransitionBarnDoorWipe : public GDKImageTransition
00348 {
00349 private:
00350     GtkWidget *window;
00351     int type;
00352 
00353 public:
00354     ImageTransitionBarnDoorWipe()
00355     {
00356         window = glade_xml_get_widget( magick_glade, "image_transition_barndoor" );
00357         GtkWidget* widget = lookup_widget( window, "optionmenu_door" );
00358         g_signal_connect( G_OBJECT( widget ), "changed", G_CALLBACK( Repaint ), 0 );
00359     }
00360 
00361     virtual ~ImageTransitionBarnDoorWipe()
00362     {
00363         gtk_widget_destroy( window );
00364     }
00365 
00366     char *GetDescription( ) const
00367     {
00368         return _( "Barn Door Wipe" );
00369     }
00370 
00371     void VerticalOpen( uint8_t *io, uint8_t *mesh, int width, int height, double position )
00372     {
00373         int roll_width = ( int ) ( width * position ) / 2;
00374         for ( int y = 0; y < height; y ++ )
00375         {
00376             uint8_t *k = mesh + y * width * 3 + ( width * 3 / 2 ) - roll_width * 3;
00377             uint8_t *p = io + y * width * 3 + ( width * 3 / 2 ) - roll_width * 3;
00378             memcpy( p, k, roll_width * 3 * 2 );
00379         }
00380     }
00381 
00382     void VerticalClose( uint8_t *io, uint8_t *mesh, int width, int height, double position )
00383     {
00384         int roll_width = ( width - ( int ) ( width * position ) ) / 2;
00385         for ( int y = 0; y < height; y ++ )
00386         {
00387             uint8_t *k = mesh + y * width * 3 + ( width * 3 / 2 ) - roll_width * 3;
00388             uint8_t *p = io + y * width * 3 + ( width * 3 / 2 ) - roll_width * 3;
00389             memcpy( p, k, roll_width * 3 * 2 );
00390         }
00391     }
00392 
00393     void HorizontalOpen( uint8_t *io, uint8_t *mesh, int width, int height, double position )
00394     {
00395         int roll_height = ( int ) ( height * position ) / 2;
00396         for ( int y = height / 2 - roll_height; y < height / 2 + roll_height; y ++ )
00397         {
00398             uint8_t *k = mesh + y * width * 3;
00399             uint8_t *p = io + y * width * 3;
00400             memcpy( p, k, width * 3 );
00401         }
00402     }
00403 
00404     void HorizontalClose( uint8_t *io, uint8_t *mesh, int width, int height, double position )
00405     {
00406         int roll_height = ( int ) ( height * position ) / 2;
00407         for ( int y = 0; y < roll_height; y ++ )
00408         {
00409             uint8_t *k = mesh + y * width * 3;
00410             uint8_t *p = io + y * width * 3;
00411             memcpy( p, k, width * 3 );
00412             k = mesh + ( height - y - 1 ) * width * 3;
00413             p = io + ( height - y - 1 ) * width * 3;
00414             memcpy( p, k, width * 3 );
00415         }
00416     }
00417 
00418     void GetFrame( uint8_t *pixels, uint8_t *mesh, int width, int height, double position, double frame_delta, bool reverse )
00419     {
00420         GtkMenu * menu = GTK_MENU( gtk_option_menu_get_menu( GTK_OPTION_MENU( lookup_widget( window, "optionmenu_door" ) ) ) );
00421         GtkWidget *active_item = gtk_menu_get_active( menu );
00422         type = g_list_index ( GTK_MENU_SHELL ( menu ) ->children, active_item );
00423         
00424         if ( type == 0 && !reverse )
00425             VerticalOpen( pixels, mesh, width, height, position );
00426         else if ( type == 0 && reverse )
00427             VerticalClose( pixels, mesh, width, height, position );
00428         else if ( type == 1 && !reverse )
00429             HorizontalOpen( pixels, mesh, width, height, position );
00430         else if ( type == 1 && reverse )
00431             HorizontalClose( pixels, mesh, width, height, position );
00432     }
00433 
00434     void AttachWidgets( GtkBin *bin )
00435     {
00436         gtk_widget_reparent( ( GTK_BIN( window ) ) ->child, GTK_WIDGET( bin ) );
00437     }
00438 
00439     void DetachWidgets( GtkBin *bin )
00440     {
00441         gtk_widget_reparent( ( GTK_BIN( bin ) ) ->child, GTK_WIDGET( window ) );
00442     }
00443 };
00444 
00445 
00449 static void
00450 on_optionmenu_selected ( GtkMenuItem *menu_item, gpointer user_data )
00451 {
00452     ( ( GDKImageTransitionRepository * ) user_data ) ->SelectionChange();
00453 }
00454 
00455 GDKImageTransitionRepository::GDKImageTransitionRepository()
00456     : selected_transition( 0 )
00457 {
00458     // Register an instance of each object (adapting raw transitions to GDK transitions where necessary)
00459     Register( new ImageTransitionFade() );
00460     Register( new ImageTransitionBarnDoorWipe() );
00461     Register( new ImageTransitionDifferences() );
00462     Register( new ImageTransitionNone() );
00463     Register( new ImageTransitionBarWipe() );
00464     Register( new ImageTransitionSwitch() );
00465 }
00466 
00467 GDKImageTransitionRepository::~GDKImageTransitionRepository()
00468 {
00469     // Remove the transitions in the repository
00470     for ( unsigned int index = 0; index < transitions.size(); index ++ )
00471         delete transitions[ index ];
00472 }
00473 
00477 void GDKImageTransitionRepository::Register( GDKImageTransition *transition )
00478 {
00479     std::cerr << ">>> Image Transition: " << transition->GetDescription() << std::endl;
00480     transitions.push_back( transition );
00481 }
00482 
00483 void GDKImageTransitionRepository::Initialise( GtkOptionMenu *menu, GtkBin *container )
00484 {
00485     // Store these for future reference
00486     this->menu = menu;
00487     this->container = container;
00488 
00489     // Add the transitions to the menu
00490     GtkMenu *menu_new = GTK_MENU( gtk_menu_new( ) );
00491     for ( unsigned int index = 0; index < transitions.size(); index ++ )
00492     {
00493         GtkWidget *item = gtk_menu_item_new_with_label( transitions[ index ] ->GetDescription( ) );
00494         gtk_widget_show( item );
00495         gtk_menu_append( menu_new, item );
00496         g_signal_connect( G_OBJECT( item ), "activate", G_CALLBACK( on_optionmenu_selected ), this );
00497     }
00498     gtk_menu_set_active( menu_new, 0 );
00499     gtk_option_menu_set_menu( menu, GTK_WIDGET( menu_new ) );
00500 
00501     // Register the selected items widgets
00502     SelectionChange();
00503 }
00504 
00505 GDKImageTransition *GDKImageTransitionRepository::Get( ) const
00506 {
00507     GtkMenu * innerMenu = GTK_MENU( gtk_option_menu_get_menu( menu ) );
00508     GtkWidget *active_item = gtk_menu_get_active( innerMenu );
00509     return transitions[ g_list_index( GTK_MENU_SHELL( innerMenu ) ->children, active_item ) ];
00510 }
00511 
00515 void GDKImageTransitionRepository::SelectionChange( )
00516 {
00517     bool isPreviewing = false;
00518     PageMagick* magick = 0;
00519 
00520     if ( common && common->getPageMagick( ) )
00521         magick = common->getPageMagick( );
00522     if ( magick && magick->IsPreviewing() )
00523     {
00524         isPreviewing = true;
00525         magick->StopPreview();
00526     }
00527 
00528     // Detach the selected Transitions widgets
00529     if ( selected_transition != NULL )
00530         selected_transition->DetachWidgets( container );
00531 
00532     if ( magick )
00533     {
00534         magick->SetKeyFrameControllerClient(0);
00535         magick->ShowCurrentStatus( magick->GetCurrentPosition(), LOCKED_KEY, false, false );
00536     }
00537 
00538     // Get the new selection
00539     selected_transition = Get();
00540 
00541     // Attach the new transition widgets
00542     if ( selected_transition != NULL )
00543         selected_transition->AttachWidgets( container );
00544 
00545     if ( magick )
00546     {
00547         if ( isPreviewing )
00548             magick->StartPreview();
00549         else
00550             magick->PreviewFrame();
00551     }
00552 }

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