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

image_create.cc

Go to the documentation of this file.
00001 /*
00002 * image_create.cc -- RGB24 image create
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 #include <glade/glade.h>
00028 #include <string.h>
00029 #include <stdio.h>
00030 #include <sys/types.h>
00031 #include <sys/stat.h>
00032 #include <unistd.h>
00033 
00034 #include "image_create.h"
00035 #include "page_magick.h"
00036 #include "message.h"
00037 #include "kino_extra.h"
00038 
00039 #define GAP_MAX (9999)
00040 
00041 extern "C"
00042 {
00043 #include "support.h"
00044     extern GladeXML* magick_glade;
00045     extern void on_time_range_changed(GtkWidget *widget, gpointer user_data);
00046 }
00047 
00048 /*
00049  * Note that for speed of development I elected to make everything GUI here, but
00050  * this will limit its use a bit. For every creator, there should be a GUI component
00051  * which extends a non-GUI component. The intention is that we should be able
00052  * to propogate state via the playlist and some unspecified sml/smil aware class
00053  * (ummm... I think that's the way I want it anyway... :-/).
00054  */
00055 
00059 class ImageCreateColour : public GDKAudioImport
00060 {
00061 protected:
00062     GdkColor start;
00063     int frames;
00064     GtkWidget *picker;
00065     GtkWidget *frame_counter;
00066 
00067 public:
00068     ImageCreateColour() : frame_counter( 0 )
00069     {
00070         start.red = start.green = start.blue = 0;
00071         frames = 25;
00072     }
00073 
00074     char *GetDescription( ) const
00075     {
00076         return _( "Fixed Colour" );
00077     }
00078 
00079     void CreateFrame( uint8_t *pixels, int width, int height, double position, double frame_delta )
00080     {
00081         if ( position == 0 )
00082         {
00083             uint8_t * p = pixels;
00084             while ( p < ( pixels + width * height * 3 ) )
00085             {
00086                 *p ++ = start.red >> 8;
00087                 *p ++ = start.green >> 8;
00088                 *p ++ = start.blue >> 8;
00089             }
00090         }
00091     }
00092 
00093     int GetNumberOfFrames( )
00094     {
00095         return frames;
00096     }
00097 
00098     void AddFrameCollector( GtkWidget *table, int row )
00099     {
00100         GtkWidget * label = gtk_label_new( _( "Frames:" ) );
00101         gtk_widget_show( label );
00102 
00103         GtkObject *frame_counter_adj = gtk_adjustment_new( frames, 0, 999999, 1, 10, 10 );
00104         frame_counter = gtk_spin_button_new( GTK_ADJUSTMENT( frame_counter_adj ), 1, 0 );
00105         gtk_spin_button_set_value( GTK_SPIN_BUTTON( frame_counter ), frames );
00106         gtk_widget_show( frame_counter );
00107         gtk_widget_set_usize( frame_counter, 60, -2 );
00108         g_signal_connect( G_OBJECT( frame_counter ), "value-changed", G_CALLBACK( on_time_range_changed ), NULL );
00109 
00110         gtk_table_attach( GTK_TABLE( table ), label, 0, 1, row, row + 1, ( GtkAttachOptions ) ( GTK_FILL ), ( GtkAttachOptions ) ( 0 ), 0, 0 );
00111         gtk_table_attach( GTK_TABLE( table ), frame_counter, 1, 2, row, row + 1, ( GtkAttachOptions ) ( 0 ), ( GtkAttachOptions ) ( 0 ), 0, 0 );
00112     }
00113 
00114     void InterpretFrameCollector( )
00115     {
00116         if ( frame_counter )
00117             frames = gtk_spin_button_get_value_as_int( GTK_SPIN_BUTTON( frame_counter ) );
00118     }
00119 
00120     void AttachWidgets( GtkBin *bin )
00121     {
00122         GtkWidget * table = gtk_table_new ( 2, 2, FALSE );
00123         gtk_table_set_row_spacings( GTK_TABLE( table ), 6 );
00124         gtk_table_set_col_spacings( GTK_TABLE( table ), 6 );
00125 
00126         GtkWidget *label = gtk_label_new( _( "Colour:" ) );
00127         gtk_widget_show( label );
00128 
00129         picker = gtk_color_button_new();
00130         gtk_color_button_set_color( GTK_COLOR_BUTTON( picker ), &start );
00131         gtk_widget_show( picker );
00132         g_signal_connect( G_OBJECT( picker ), "color-set", G_CALLBACK( Repaint ), 0 );
00133 
00134         AddFrameCollector( table, 0 );
00135 
00136         gtk_table_attach( GTK_TABLE( table ), label, 0, 1, 1, 2, ( GtkAttachOptions ) ( 0 ), ( GtkAttachOptions ) ( 0 ), 0, 0 );
00137         gtk_table_attach( GTK_TABLE( table ), picker, 1, 2, 1, 2, ( GtkAttachOptions ) ( 0 ), ( GtkAttachOptions ) ( 0 ), 0, 0 );
00138 
00139         gtk_widget_show( table );
00140         gtk_container_add( GTK_CONTAINER( bin ), table );
00141     }
00142 
00143     void DetachWidgets( GtkBin *bin )
00144     {
00145         if ( bin->child != NULL )
00146         {
00147             InterpretFrameCollector( );
00148             gtk_color_button_get_color( GTK_COLOR_BUTTON( picker ), &start );
00149             gtk_container_remove( GTK_CONTAINER( bin ), bin->child );
00150         }
00151     }
00152 
00153     void InterpretWidgets( GtkBin *bin )
00154     {
00155         if ( bin->child != NULL )
00156         {
00157             InterpretFrameCollector( );
00158             gtk_color_button_get_color( GTK_COLOR_BUTTON( picker ), &start );
00159         }
00160     }
00161 
00162     void CreateAudio( int16_t **buffer, short int *channels, int *frequency, int *samples )
00163     {}
00164 }
00165 ;
00166 
00170 class ImageCreateNoise : public ImageCreateColour
00171 {
00172 public:
00173     char *GetDescription( ) const
00174     {
00175         return _( "Random noise" );
00176     }
00177 
00178     void CreateFrame( uint8_t *pixels, int width, int height, double position, double frame_delta )
00179     {
00180         uint8_t value;
00181         uint8_t *p = pixels;
00182         while ( p < ( pixels + width * height * 3 ) )
00183         {
00184             value = ( uint8_t ) ( 255.0 * rand() / ( RAND_MAX + 1.0 ) );
00185             *p ++ = value;
00186             *p ++ = value;
00187             *p ++ = value;
00188         }
00189     }
00190 
00191     void AttachWidgets( GtkBin *bin )
00192     {
00193         GtkWidget * table = gtk_table_new ( 2, 2, FALSE );
00194         gtk_table_set_row_spacings( GTK_TABLE( table ), 6 );
00195         gtk_table_set_col_spacings( GTK_TABLE( table ), 6 );
00196         AddFrameCollector( table, 0 );
00197         gtk_widget_show( table );
00198         gtk_container_add( GTK_CONTAINER( bin ), table );
00199     }
00200 
00201     void DetachWidgets( GtkBin *bin )
00202     {
00203         if ( bin->child != NULL )
00204         {
00205             InterpretFrameCollector( );
00206             gtk_container_remove( GTK_CONTAINER( bin ), bin->child );
00207         }
00208     }
00209 
00210     void InterpretWidgets( GtkBin *bin )
00211     {
00212         if ( bin->child != NULL )
00213             InterpretFrameCollector( );
00214     }
00215 };
00216 
00220 class ImageCreateColourRange : public ImageCreateColour
00221 {
00222 protected:
00223     GdkColor end;
00224     GtkWidget *start_picker;
00225     GtkWidget *end_picker;
00226 
00227 public:
00228     ImageCreateColourRange()
00229     {
00230         end.red = end.green = end.blue = 0;
00231     }
00232 
00233     char *GetDescription( ) const
00234     {
00235         return _( "Colour Range" );
00236     }
00237 
00238     void CreateFrame( uint8_t *pixels, int width, int height, double position, double frame_delta )
00239     {
00240         uint8_t r = start.red + guint16( ( end.red - start.red ) * position ) >> 8 ;
00241         uint8_t g = start.green + guint16( ( end.green - start.green ) * position ) >> 8;
00242         uint8_t b = start.blue + guint16( ( end.blue - start.blue ) * position ) >> 8;
00243         uint8_t *p = pixels;
00244         while ( p < ( pixels + width * height * 3 ) )
00245         {
00246             *p ++ = r;
00247             *p ++ = g;
00248             *p ++ = b;
00249         }
00250     }
00251 
00252     void AttachWidgets( GtkBin *bin )
00253     {
00254         GtkWidget * table = gtk_table_new( 2, 4, FALSE );
00255         gtk_table_set_row_spacings( GTK_TABLE( table ), 6 );
00256         gtk_table_set_col_spacings( GTK_TABLE( table ), 6 );
00257 
00258         GtkWidget *start_label = gtk_label_new( _( "From:" ) );
00259         gtk_widget_show( start_label );
00260 
00261         start_picker = gtk_color_button_new();
00262         gtk_color_button_set_color( GTK_COLOR_BUTTON( start_picker ), &start );
00263         gtk_widget_show( start_picker );
00264         g_signal_connect( G_OBJECT( start_picker ), "color-set", G_CALLBACK( Repaint ), 0 );
00265 
00266         GtkWidget *end_label = gtk_label_new( _( "To:" ) );
00267         gtk_widget_show( end_label );
00268 
00269         end_picker = gtk_color_button_new();
00270         gtk_color_button_set_color( GTK_COLOR_BUTTON( end_picker ), &end );
00271         gtk_widget_show( end_picker );
00272         g_signal_connect( G_OBJECT( end_picker ), "color-set", G_CALLBACK( Repaint ), 0 );
00273 
00274         AddFrameCollector( table, 0 );
00275 
00276         gtk_table_attach( GTK_TABLE( table ), start_label, 0, 1, 1, 2, ( GtkAttachOptions ) ( GTK_FILL ), ( GtkAttachOptions ) ( 0 ), 0, 0 );
00277         gtk_table_attach( GTK_TABLE( table ), start_picker, 1, 2, 1, 2, ( GtkAttachOptions ) ( 0 ), ( GtkAttachOptions ) ( 0 ), 0, 0 );
00278         gtk_table_attach( GTK_TABLE( table ), end_label, 2, 3, 1, 2, ( GtkAttachOptions ) ( GTK_FILL ), ( GtkAttachOptions ) ( 0 ), 0, 0 );
00279         gtk_table_attach( GTK_TABLE( table ), end_picker, 3, 4, 1, 2, ( GtkAttachOptions ) ( 0 ), ( GtkAttachOptions ) ( 0 ), 0, 0 );
00280 
00281         gtk_widget_show( table );
00282         gtk_container_add( GTK_CONTAINER( bin ), table );
00283     }
00284 
00285     void DetachWidgets( GtkBin *bin )
00286     {
00287         if ( bin->child != NULL )
00288         {
00289             InterpretFrameCollector( );
00290             gtk_color_button_get_color( GTK_COLOR_BUTTON( start_picker ), &start );
00291             gtk_color_button_get_color( GTK_COLOR_BUTTON( end_picker ), &end );
00292             gtk_container_remove( GTK_CONTAINER( bin ), bin->child );
00293         }
00294     }
00295 
00296     void InterpretWidgets( GtkBin *bin )
00297     {
00298         if ( bin->child != NULL )
00299         {
00300             InterpretFrameCollector( );
00301             gtk_color_button_get_color( GTK_COLOR_BUTTON( start_picker ), &start );
00302             gtk_color_button_get_color( GTK_COLOR_BUTTON( end_picker ), &end );
00303         }
00304     }
00305 };
00306 
00310 class ImageCreateGradiate : public GDKImageCreate
00311 {
00312 private:
00313     GtkWidget *window;
00314     GdkColor start_left, start_right, end_left, end_right, start, end;
00315     int type;
00316     int frames;
00317 
00318 public:
00319     ImageCreateGradiate()
00320     {
00321         window = glade_xml_get_widget( magick_glade, "image_create_gradiate" );
00322         start_right.red = start_right.green = start_right.blue = 0;
00323         GtkWidget* widget = lookup_widget( window, "colorpicker_start_right" );
00324         gtk_color_button_set_color( GTK_COLOR_BUTTON( widget ), &start_right );
00325         g_signal_connect( G_OBJECT( widget ), "color-set", G_CALLBACK( Repaint ), 0 );
00326 
00327         end_right.red = end_right.green = end_right.blue = 0;
00328         widget = lookup_widget( window, "colorpicker_end_right" );
00329         gtk_color_button_set_color( GTK_COLOR_BUTTON( widget ), &end_right );
00330         g_signal_connect( G_OBJECT( widget ), "color-set", G_CALLBACK( Repaint ), 0 );
00331 
00332         widget = lookup_widget( window, "optionmenu_gradiate" );
00333         g_signal_connect( G_OBJECT( widget ), "changed", G_CALLBACK( Repaint ), 0 );
00334         widget = lookup_widget( window, "colorpicker_start_left" );
00335         g_signal_connect( G_OBJECT( widget ), "color-set", G_CALLBACK( Repaint ), 0 );
00336         widget = lookup_widget( window, "colorpicker_end_left" );
00337         g_signal_connect( G_OBJECT( widget ), "color-set", G_CALLBACK( Repaint ), 0 );
00338     }
00339 
00340     virtual ~ImageCreateGradiate()
00341     {
00342         gtk_widget_destroy( window );
00343     }
00344 
00345     char *GetDescription( ) const
00346     {
00347         return _( "Gradient" );
00348     }
00349 
00350     void LeftMiddle( uint8_t *pixels, int width, int height, double position )
00351     {
00352         double rr = ( double ) ( end.red - start.red ) / ( double ) ( width ) * 2;
00353         double rg = ( double ) ( end.green - start.green ) / ( double ) ( width ) * 2;
00354         double rb = ( double ) ( end.blue - start.blue ) / ( double ) ( width ) * 2;
00355         uint8_t *p = pixels;
00356         for ( int y = 0; y < height; y ++ )
00357         {
00358             for ( int x = 0; x < width; x ++ )
00359             {
00360                 if ( x < width / 2 )
00361                 {
00362                     *p ++ = guint16( start.red + rr * x ) >> 8;
00363                     *p ++ = guint16( start.green + rg * x ) >> 8;
00364                     *p ++ = guint16( start.blue + rb * x ) >> 8;
00365                 }
00366                 else
00367                 {
00368                     int o = width / 2 - ( x - width / 2 );
00369                     *p ++ = guint16( start.red + rr * o ) >> 8;
00370                     *p ++ = guint16( start.green + rg * o ) >> 8;
00371                     *p ++ = guint16( start.blue + rb * o ) >> 8;
00372                 }
00373             }
00374         }
00375     }
00376 
00377     void LeftRight( uint8_t *pixels, int width, int height, double position )
00378     {
00379         double rr = ( double ) ( end.red - start.red ) / ( double ) ( width );
00380         double rg = ( double ) ( end.green - start.green ) / ( double ) ( width );
00381         double rb = ( double ) ( end.blue - start.blue ) / ( double ) ( width );
00382         uint8_t *p = pixels;
00383         for ( int y = 0; y < height; y ++ )
00384         {
00385             for ( int x = 0; x < width; x ++ )
00386             {
00387                 *p ++ = guint16( start.red + rr * x ) >> 8;
00388                 *p ++ = guint16( start.green + rg * x ) >> 8;
00389                 *p ++ = guint16( start.blue + rb * x ) >> 8;
00390             }
00391         }
00392     }
00393 
00394     void TopBottom( uint8_t *pixels, int width, int height, double position )
00395     {
00396         double rr = ( double ) ( end.red - start.red ) / ( double ) ( height );
00397         double rg = ( double ) ( end.green - start.green ) / ( double ) ( height );
00398         double rb = ( double ) ( end.blue - start.blue ) / ( double ) ( height );
00399         uint8_t *p = pixels;
00400         for ( int y = 0; y < height; y ++ )
00401         {
00402             for ( int x = 0; x < width; x ++ )
00403             {
00404                 *p ++ = guint16( start.red + rr * y ) >> 8;
00405                 *p ++ = guint16( start.green + rg * y ) >> 8;
00406                 *p ++ = guint16( start.blue + rb * y ) >> 8;
00407             }
00408         }
00409     }
00410 
00411     void TopMiddle( uint8_t *pixels, int width, int height, double position )
00412     {
00413         double rr = ( double ) ( end.red - start.red ) / ( double ) ( height ) * 2;
00414         double rg = ( double ) ( end.green - start.green ) / ( double ) ( height ) * 2;
00415         double rb = ( double ) ( end.blue - start.blue ) / ( double ) ( height ) * 2;
00416         uint8_t *p = pixels;
00417         for ( int y = 0; y < height; y ++ )
00418         {
00419             for ( int x = 0; x < width; x ++ )
00420             {
00421                 if ( y < height / 2 )
00422                 {
00423                     *p ++ = guint16( start.red + rr * y ) >> 8;
00424                     *p ++ = guint16( start.green + rg * y ) >> 8;
00425                     *p ++ = guint16( start.blue + rb * y ) >> 8;
00426                 }
00427                 else
00428                 {
00429                     int o = height / 2 - ( y - height / 2 );
00430                     *p ++ = guint16( start.red + rr * o ) >> 8;
00431                     *p ++ = guint16( start.green + rg * o ) >> 8;
00432                     *p ++ = guint16( start.blue + rb * o ) >> 8;
00433                 }
00434             }
00435         }
00436     }
00437 
00438     void CreateFrame( uint8_t *pixels, int width, int height, double position, double frame_delta )
00439     {
00440         start.red = start_left.red + guint16( ( end_left.red - start_left.red ) * position );
00441         start.green = start_left.green + guint16( ( end_left.green - start_left.green ) * position );
00442         start.blue = start_left.blue + guint16( ( end_left.blue - start_left.blue ) * position );
00443 
00444         end.red = start_right.red + guint16( ( end_right.red - start_right.red ) * position );
00445         end.green = start_right.green + guint16( ( end_right.green - start_right.green ) * position );
00446         end.blue = start_right.blue + guint16( ( end_right.blue - start_right.blue ) * position );
00447 
00448         if ( type == 0 )
00449             LeftMiddle( pixels, width, height, position );
00450         else if ( type == 1 )
00451             LeftRight( pixels, width, height, position );
00452         else if ( type == 2 )
00453             TopBottom( pixels, width, height, position );
00454         else if ( type == 3 )
00455             TopMiddle( pixels, width, height, position );
00456     }
00457 
00458     void AttachWidgets( GtkBin *bin )
00459     {
00460         gtk_widget_reparent( ( GTK_BIN( window ) ) ->child, GTK_WIDGET( bin ) );
00461     }
00462 
00463     void DetachWidgets( GtkBin *bin )
00464     {
00465         gtk_widget_reparent( ( GTK_BIN( bin ) ) ->child, GTK_WIDGET( window ) );
00466     }
00467 
00468     void InterpretWidgets( GtkBin *bin )
00469     {
00470         if ( bin->child != NULL )
00471         {
00472             GtkMenu * menu = GTK_MENU( gtk_option_menu_get_menu( GTK_OPTION_MENU( lookup_widget( window, "optionmenu_gradiate" ) ) ) );
00473             GtkWidget *active_item = gtk_menu_get_active( menu );
00474             type = g_list_index ( GTK_MENU_SHELL ( menu ) ->children, active_item );
00475     
00476             GtkEntry *entry = GTK_ENTRY( lookup_widget( window, "spinbutton_frames" ) );
00477             frames = atoi( gtk_entry_get_text( entry ) );
00478     
00479             gtk_color_button_get_color( GTK_COLOR_BUTTON( lookup_widget( window, "colorpicker_start_left" ) ),
00480                                     &start_left );
00481             gtk_color_button_get_color( GTK_COLOR_BUTTON( lookup_widget( window, "colorpicker_start_right" ) ),
00482                                     &start_right );
00483             gtk_color_button_get_color( GTK_COLOR_BUTTON( lookup_widget( window, "colorpicker_end_left" ) ),
00484                                     &end_left );
00485             gtk_color_button_get_color( GTK_COLOR_BUTTON( lookup_widget( window, "colorpicker_end_right" ) ),
00486                                     &end_right );
00487         }
00488     }
00489 
00490     int GetNumberOfFrames( )
00491     {
00492         return frames;
00493     }
00494 };
00495 
00499 class ImageCreateFromFile : public ImageCreateColourRange
00500 {
00501 protected:
00502     static char file[ PATH_MAX + NAME_MAX ];
00503     GtkWidget *file_entry;
00504     int count;
00505     GdkPixbuf* still;
00506     bool hasFilenameChanged;
00507     int count_offset;
00508 
00509 public:
00510     ImageCreateFromFile( )
00511         : file_entry( 0 )
00512         , still( 0 ) 
00513         , hasFilenameChanged( false )
00514         , count_offset( 0 )
00515     { }
00516 
00517     char *GetDescription( ) const
00518     {
00519         return _( "From File" );
00520     }
00521 
00522     void CreateFrame( uint8_t *pixels, int width, int height, double position, double frame_delta )
00523     {
00524         if ( strcmp( file, "" ) == 0 )
00525             return;
00526         
00527         GError* gerror = NULL;
00528         SelectedFrames& fx = GetSelectedFramesForFX();
00529 
00530         // Determine if this is an image sequence
00531         if ( strchr( file, '%' ) != NULL )
00532         {
00533             char full[ PATH_MAX + NAME_MAX ];
00534             int gap = 0;
00535         
00536             if ( fx.IsRepainting() || fx.IsPreviewing() )
00537             {
00538                 // compute the relative count
00539                 count = int( position * GetNumberOfFrames() + 0.5 );
00540                 
00541                 // determine offset to first file
00542                 if ( hasFilenameChanged )
00543                 for ( count_offset = 0; count_offset < GAP_MAX; ++count_offset )
00544                 {
00545                     struct stat buf;
00546                     snprintf( full, PATH_MAX + NAME_MAX, file, count + count_offset );
00547                     if ( stat( full, &buf ) == 0 )
00548                         break;
00549                 }
00550                 count += count_offset;
00551             }
00552             // Permit gaps in the file number sequence
00553             while ( gap < GAP_MAX )
00554             {
00555                 struct stat buf;
00556                 snprintf( full, PATH_MAX + NAME_MAX, file, count++ );
00557                 if ( stat( full, &buf ) == 0 )
00558                     break;
00559                 else
00560                     gap ++;
00561             }
00562             // If successfully obtained a new file
00563             if ( gap < GAP_MAX )
00564             {
00565                 GdkPixbuf *image = gdk_pixbuf_new_from_file( full, &gerror );
00566                 if ( still )
00567                     g_object_unref( still );
00568                 still = gdk_pixbuf_scale_simple( image, width, height, GDK_INTERP_HYPER );
00569                 g_object_unref( image );
00570             }
00571         }
00572         // Otherwise, import single image just once
00573         else if ( hasFilenameChanged )
00574         {
00575             GdkPixbuf *image = gdk_pixbuf_new_from_file( file, &gerror );
00576             if ( still )
00577                 g_object_unref( still );
00578             if ( image )
00579             {
00580                 still = gdk_pixbuf_scale_simple( image, width, height, GDK_INTERP_HYPER );
00581                 g_object_unref( image );
00582             }
00583         }
00584         // If gdk-pixbuf loader generated an error
00585         if ( gerror != NULL )
00586         {
00587             if ( hasFilenameChanged )
00588             {
00589                 if ( fx.IsPreviewing() )
00590                     gdk_threads_enter();
00591                 modal_message( gerror->message );
00592                 if ( fx.IsPreviewing() )
00593                     gdk_threads_leave();
00594             }
00595             g_error_free( gerror );
00596             if ( still )
00597                 g_object_unref( still );
00598             still = 0;
00599         }
00600         // Otherwise, if there is a pixbuf
00601         else if ( still )
00602         {
00603             if ( gdk_pixbuf_get_has_alpha( still ) ) {
00604             // This is a hack! The correct calls would be:
00605             // gdk_pixbuf_new/gdk_pixbuf_copy_area
00606                 uint8_t *jp = gdk_pixbuf_get_pixels( still ), *jz = pixels;
00607                 for ( int i = 0; i < width * height; i++ ) {
00608                     memcpy( jz, jp, 3 );
00609                     jp += 4; jz += 3;
00610                 }
00611             }
00612             else
00613                 memcpy( pixels, gdk_pixbuf_get_pixels( still ), width * height * 3 );
00614         }
00615         hasFilenameChanged = false;
00616     }
00617 
00618     static void
00619     on_button_file_clicked( GtkButton *button, gpointer user_data )
00620     {
00621         char *filename = common->getFileToOpen( _("Select an Image"), false );
00622         if ( filename && strcmp( filename, "" ) )
00623         {
00624             ImageCreateFromFile *me = static_cast< ImageCreateFromFile* >( user_data );
00625             gtk_entry_set_text( me->getEntry(), filename );
00626         }
00627     }
00628     
00629     void AttachWidgets( GtkBin *bin )
00630     {
00631         GtkWidget * table = gtk_table_new ( 2, 2, FALSE );
00632         gtk_table_set_row_spacings( GTK_TABLE( table ), 6 );
00633         gtk_table_set_col_spacings( GTK_TABLE( table ), 6 );
00634 
00635         GtkWidget *label = gtk_label_new( _( "File:" ) );
00636         gtk_widget_show( label );
00637 
00638         GtkWidget *hbox = gtk_hbox_new( FALSE, 6 );
00639         file_entry = gtk_entry_new();
00640         gtk_entry_set_text( GTK_ENTRY( file_entry ), file );
00641         g_signal_connect( G_OBJECT( file_entry ), "activate", G_CALLBACK( Repaint ), 0 );
00642         gtk_box_pack_start( GTK_BOX( hbox ), file_entry, TRUE, TRUE, 0 );
00643         GtkWidget *button = gtk_button_new();
00644         GtkWidget *image = gtk_image_new_from_stock( GTK_STOCK_OPEN, GTK_ICON_SIZE_BUTTON );
00645         gtk_container_add( GTK_CONTAINER( button ), image );
00646         gtk_button_set_relief( GTK_BUTTON( button ), GTK_RELIEF_NONE );
00647         g_signal_connect( G_OBJECT( button ), "clicked", G_CALLBACK( on_button_file_clicked ), this );
00648 
00649         gtk_box_pack_start( GTK_BOX( hbox ), button, FALSE, TRUE, 0 );
00650         gtk_widget_show( hbox );
00651         gtk_widget_show( file_entry );
00652         gtk_widget_show( button );
00653         gtk_widget_show( image );
00654 
00655         AddFrameCollector( table, 0 );
00656         gtk_table_attach( GTK_TABLE( table ), label, 0, 1, 1, 2, ( GtkAttachOptions ) ( 0 ), ( GtkAttachOptions ) ( 0 ), 0, 0 );
00657         gtk_table_attach( GTK_TABLE( table ), hbox, 1, 2, 1, 2, ( GtkAttachOptions ) ( GTK_EXPAND | GTK_FILL | GTK_SHRINK ), ( GtkAttachOptions ) ( 0 ), 0, 0 );
00658 
00659         GtkWidget *tip_label = gtk_label_new( _( "TIP: use a format specifier in the file name\nto import from an image sequence.\nFor example: gap-%06d.png." ) );
00660         gtk_label_set_line_wrap( GTK_LABEL( tip_label ), FALSE );
00661         gtk_widget_show( tip_label );
00662         gtk_table_attach( GTK_TABLE( table ), tip_label, 0, 2, 2, 3, ( GtkAttachOptions ) ( GTK_EXPAND | GTK_FILL | GTK_SHRINK ), ( GtkAttachOptions ) ( 0 ), 0, 0 );
00663 
00664         gtk_widget_show( table );
00665         gtk_container_add( GTK_CONTAINER( bin ), table );
00666     }
00667 
00668     void DetachWidgets( GtkBin *bin )
00669     {
00670         if ( bin->child != NULL )
00671         {
00672             // Make sure we save the current settings (this should be a method, rather than a duplicate
00673             // of InterpretWidgets ... since Interpret may throw exceptions, it can't be called directly
00674             // here...)
00675             InterpretFrameCollector( );
00676             strcpy( file, gtk_entry_get_text( GTK_ENTRY( file_entry ) ) );
00677             gtk_container_remove( GTK_CONTAINER( bin ), bin->child );
00678         }
00679     }
00680 
00681     void InterpretWidgets( GtkBin *bin )
00682     {
00683         if ( bin->child != NULL )
00684         {
00685             InterpretFrameCollector( );
00686             if ( file_entry )
00687             {
00688                 int n = PATH_MAX + NAME_MAX - 1;
00689                 char newFileName[ n + 1 ];
00690                 newFileName[ n ] = '\0';
00691                 strncpy( newFileName, gtk_entry_get_text( GTK_ENTRY( file_entry ) ), n );
00692                 SelectedFrames& fx = GetSelectedFramesForFX();
00693                 if ( strcmp( newFileName, file ) || !( fx.IsRepainting() || fx.IsPreviewing() ) )
00694                     hasFilenameChanged = true;
00695                 strcpy( file, newFileName );
00696                 count = 0;
00697             }
00698         }
00699     }
00700 
00701     GtkEntry *getEntry() const
00702     {
00703         if ( file_entry )
00704             return GTK_ENTRY( file_entry );
00705         else
00706             return NULL;
00707     }
00708 };
00709 
00710 char ImageCreateFromFile::file[ PATH_MAX + NAME_MAX ] = "";
00711 
00715 static void
00716 on_optionmenu_selected ( GtkMenuItem *menu_item, gpointer user_data )
00717 {
00718     ( ( GDKImageCreateRepository * ) user_data ) ->SelectionChange();
00719 }
00720 
00726 GDKImageCreateRepository::GDKImageCreateRepository() : selected_creator( NULL ), menu( NULL ), container( NULL )
00727 {
00728     // Register an instance of each object
00729     Register( new ImageCreateColourRange() );
00730     Register( new ImageCreateColour() );
00731     Register( new ImageCreateFromFile() );
00732     Register( new ImageCreateGradiate() );
00733     Register( new ImageCreateNoise() );
00734 }
00735 
00739 GDKImageCreateRepository::~GDKImageCreateRepository()
00740 {
00741     // Remove the creators in the repository
00742     for ( unsigned int index = 0; index < creators.size(); index ++ )
00743         delete creators[ index ];
00744 }
00745 
00749 void GDKImageCreateRepository::Register( GDKImageCreate *creator )
00750 {
00751     std::cerr <<  ">>> Image Create: " << creator->GetDescription( ) << std::endl;
00752     creators.push_back( creator );
00753 }
00754 
00758 void GDKImageCreateRepository::Initialise( GtkOptionMenu *menu, GtkBin *container )
00759 {
00760     // Store these for future reference
00761     this->menu = menu;
00762     this->container = container;
00763 
00764     // Add the creators to the menu
00765     GtkMenu *menu_new = GTK_MENU( gtk_menu_new( ) );
00766     for ( unsigned int index = 0; index < creators.size(); index ++ )
00767     {
00768         GtkWidget *item = gtk_menu_item_new_with_label( creators[ index ] ->GetDescription( ) );
00769         gtk_widget_show( item );
00770         gtk_menu_append( menu_new, item );
00771         g_signal_connect( G_OBJECT( item ), "activate", G_CALLBACK( on_optionmenu_selected ), this );
00772     }
00773     gtk_menu_set_active( menu_new, 0 );
00774     gtk_option_menu_set_menu( menu, GTK_WIDGET( menu_new ) );
00775 
00776     // Register the selected items widgets
00777     SelectionChange();
00778 }
00779 
00783 GDKImageCreate *GDKImageCreateRepository::Get( ) const
00784 {
00785     GtkMenu * creatorMenu = GTK_MENU( gtk_option_menu_get_menu( menu ) );
00786     GtkWidget *active_item = gtk_menu_get_active( creatorMenu );
00787     return creators[ g_list_index( GTK_MENU_SHELL( creatorMenu ) ->children, active_item ) ];
00788 }
00789 
00793 void GDKImageCreateRepository::SelectionChange( )
00794 {
00795     // Detach the selected creators widgets
00796     if ( selected_creator != NULL )
00797         selected_creator->DetachWidgets( container );
00798 
00799     // Get the new selection
00800     selected_creator = Get();
00801 
00802     // Attach the new creators widgets
00803     if ( selected_creator != NULL )
00804         selected_creator->AttachWidgets( container );
00805 
00806     // Inform the main page of the change
00807     if ( common != NULL && common->getPageMagick( ) != NULL )
00808         common->getPageMagick( ) ->RefreshStatus( );
00809 }

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