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

page_export_stills.cc

Go to the documentation of this file.
00001 /*
00002 * page_export_stills.cc Notebook Firewire/AVI/Still Frame Export Page Object
00003 * Copyright (C) 2001-2007 Dan Dennedy <dan@dennedy.org>
00004 *
00005 * This program is free software; you can redistribute it and/or modify
00006 * it under the terms of the GNU General Public License as published by
00007 * the Free Software Foundation; either version 2 of the License, or
00008 * (at your option) any later version.
00009 *
00010 * This program is distributed in the hope that it will be useful,
00011 * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013 * GNU General Public License for more details.
00014 *
00015 * You should have received a copy of the GNU General Public License
00016 * along with this program; if not, write to the Free Software Foundation,
00017 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00018 */
00019 
00020 #ifdef HAVE_CONFIG_H
00021 #include <config.h>
00022 #endif
00023 
00024 #include <vector>
00025 #include <iostream>
00026 using std::cerr;
00027 using std::endl;
00028 
00029 #include <gtk/gtk.h>
00030 #include <stdio.h>
00031 #include <stdlib.h>
00032 
00033 #include "page_export_stills.h"
00034 #include "preferences.h"
00035 #include "kino_common.h"
00036 #include "frame.h"
00037 #include "page_editor.h"
00038 #include "message.h"
00039 
00046 ExportStills::ExportStills( PageExport *_exportPage, KinoCommon *_common ) :
00047         Export( _exportPage, _common )
00048 {
00049     cerr << "> Creating ExportStills Page" << endl;
00050 
00051     /* Get a pointer to the controls of this page */
00052     qualityScale
00053     = GTK_RANGE( lookup_widget( common->getWidget(), "hscale_export_stills" ) );
00054 
00055     fileEntry
00056     = GTK_ENTRY( lookup_widget( common->getWidget(), "entry_export_stills_file" ) );
00057 }
00058 
00062 ExportStills::~ExportStills()
00063 {
00064     cerr << "> Destroying ExportStills Page" << endl;
00065 }
00066 
00069 enum export_result
00070 ExportStills::doExport( PlayList * playlist, int begin, int end, int every,
00071                         bool preview )
00072 {
00073     static unsigned char pixels[ FRAME_MAX_WIDTH * FRAME_MAX_HEIGHT * 4 ];
00074     GdkPixbuf *image = NULL;
00075     gchar *file = NULL;
00076     gchar *filename = NULL;
00077     gchar *extension = NULL;
00078     int i = -1;
00079     GError *gerror = NULL;
00080     char quality[ 8 ] = "75";
00081     int extractOption;
00082     bool isResample;
00083 
00084     file = g_strdup( gtk_entry_get_text( fileEntry ) );
00085 
00086     /* Check for a valid filename */
00087     if ( !strcmp( file, "" ) )
00088     {
00089         modal_message( _( "You must enter a filename." ) );
00090         g_free( file );
00091         return EXPORT_RESULT_FAILURE;
00092     }
00093 
00094     /* Take care of the quality parameter */
00095     GtkAdjustment * adjust = gtk_range_get_adjustment( qualityScale );
00096     if ( adjust )
00097         snprintf( quality, 8, "%d", ( int ) adjust->value );
00098 
00099     /* make sure a file extension is supplied */
00100     char *tmp = strrchr( file, '.' );
00101     if ( tmp == NULL )
00102     {
00103         modal_message( _( "You must enter a filename with an extension" ) );
00104         g_free( file );
00105         return EXPORT_RESULT_FAILURE;
00106     }
00107     else
00108     {
00109         extension = g_strdup( tmp );
00110         tmp[0] = '\0';
00111     }
00112 
00113     /* get the frame extraction method */
00114     GtkWidget *widget = gtk_option_menu_get_menu( GTK_OPTION_MENU( lookup_widget( common->getWidget(),
00115         "optionmenu_export_stills_extract" ) ) );
00116     GtkWidget *active_item = gtk_menu_get_active( GTK_MENU( widget ) );
00117     extractOption = g_list_index( GTK_MENU_SHELL( widget )->children, active_item );
00118         
00119     widget = lookup_widget( common->getWidget(), "checkbutton_export_stills_resample" );
00120     isResample = gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( widget ) );
00121         
00122     /* Iterate over all frames in selection */
00123     Frame &frame = *GetFramePool( ) ->GetFrame( );
00124     frame.decoder->quality = DV_QUALITY_BEST;
00125 
00126     for ( i = begin; i <= end && exportPage->isExporting; i += every )
00127     {
00128 
00129         /* Call innerLoopUpdate */
00130         innerLoopUpdate( i, begin, end, every );
00131 
00132         // Extract pixel data
00133         playlist->GetFrame( i, frame );
00134         frame.ExtractRGB( pixels );
00135         switch ( extractOption )
00136         {
00137             case 1:
00138                 frame.Deinterlace( ( uint8_t* ) pixels, ( uint8_t* ) pixels, frame.GetWidth() * 3, frame.GetHeight() );
00139                 break;
00140             case 2:
00141                 frame.GetLowerField( pixels, 3 );
00142                 break;
00143             case 3:
00144                 frame.GetUpperField( pixels, 3 );
00145                 break;
00146             default:
00147                 break;
00148         }
00149 
00150         // Get gdk-pixbuf
00151         image = gdk_pixbuf_new_from_data( pixels, GDK_COLORSPACE_RGB, FALSE, 8,
00152                                           frame.GetWidth(), frame.GetHeight(), frame.GetWidth() * 3, NULL, NULL );
00153 
00154         // Adjust pixel aspect
00155         if ( isResample )
00156         {
00157             int width = frame.GetWidth();
00158             if ( frame.IsWide() )
00159                 width = frame.IsPAL() ? 1024 : 854;
00160             AspectRatioCalculator calc( width, frame.GetHeight(),
00161                                     frame.GetWidth(), frame.GetHeight(),
00162                                     frame.IsPAL(), frame.IsWide() );
00163             GdkPixbuf *scaled = gdk_pixbuf_scale_simple( image, calc.width, calc.height, GDK_INTERP_HYPER );
00164             g_object_unref( image );
00165             image = scaled;
00166         }
00167         
00168         // save to image
00169         filename = g_strdup_printf( "%s_%06i%s", file, i + 1, extension );
00170         if ( strncasecmp( extension + 1, "png", 8 ) == 0 )
00171             gdk_pixbuf_save( image, filename, "png", &gerror, NULL );
00172         else
00173             gdk_pixbuf_save( image, filename, "jpeg", &gerror, "quality", quality, NULL );
00174 
00175         if ( gerror != NULL )
00176         {
00177             modal_message( gerror->message );
00178             g_error_free( gerror );
00179         }
00180         g_object_unref( image );
00181         g_free( filename );
00182     }
00183 
00184     GetFramePool( ) ->DoneWithFrame( &frame );
00185     
00186     g_free( file );
00187     g_free( extension );
00188 
00189     if ( !exportPage->isExporting )
00190         return EXPORT_RESULT_ABORT;
00191     else if ( i > end )
00192         return EXPORT_RESULT_SUCCESS;
00193     else
00194         return EXPORT_RESULT_FAILURE;
00195 }
00196 
00197 extern "C"
00198 {
00199     void
00200     on_button_export_stills_file_clicked    (GtkButton       *button,
00201                                             gpointer         user_data)
00202     {
00203         const char *filename = common->getFileToSave( _("Enter a File Name to Save As") );
00204         gtk_widget_grab_focus( lookup_widget( GTK_WIDGET( button ), "entry_export_stills_file" ) );
00205         if ( strcmp( filename, "" ) )
00206             gtk_entry_set_text( GTK_ENTRY( lookup_widget( GTK_WIDGET( button ), "entry_export_stills_file" ) ), filename );
00207     }
00208 }

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