~ubuntu-branches/ubuntu/trusty/shutter/trusty

« back to all changes in this revision

Viewing changes to share/shutter/resources/system/plugins/perl/spbardistortion/spbardistortion

  • Committer: Bazaar Package Importer
  • Author(s): Ryan Niebur
  • Date: 2009-08-06 16:29:32 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20090806162932-g00c3k4obbdddb4u
Tags: 0.80.1-1
* New Upstream Version
  - update copyright

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#! /usr/bin/env perl
 
2
 
 
3
###################################################
 
4
#
 
5
#  Copyright (C) 2008, 2009 Mario Kemper <mario.kemper@googlemail.com> and Shutter Team
 
6
#
 
7
#  This file is part of Shutter.
 
8
#
 
9
#  Shutter is free software; you can redistribute it and/or modify
 
10
#  it under the terms of the GNU General Public License as published by
 
11
#  the Free Software Foundation; either version 3 of the License, or
 
12
#  (at your option) any later version.
 
13
#
 
14
#  Shutter is distributed in the hope that it will be useful,
 
15
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
16
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
17
#  GNU General Public License for more details.
 
18
#
 
19
#  You should have received a copy of the GNU General Public License
 
20
#  along with Shutter; if not, write to the Free Software
 
21
#  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
22
#
 
23
###################################################
 
24
 
 
25
use utf8;
 
26
use strict;
 
27
use warnings;
 
28
use Gtk2 '-init';
 
29
use Image::Magick;
 
30
use POSIX qw/setlocale strftime/;
 
31
use Locale::gettext;
 
32
use Glib qw/TRUE FALSE/;
 
33
use FindBin '$Bin';    #path where plugin is located
 
34
use File::Temp qw/ tempfile tempdir /;
 
35
use Time::HiRes qw/usleep/;
 
36
 
 
37
#load modules at custom path at runtime
 
38
#--------------------------------------
 
39
require lib;
 
40
import lib $ENV{'SHUTTER_ROOT'}."/share/shutter/resources/modules";
 
41
 
 
42
#proc (Thanks to Michael Schilli)
 
43
require Proc::Simple;
 
44
 
 
45
#load shutter's modules
 
46
#--------------------------------------
 
47
require Shutter::App::SimpleDialogs;
 
48
 
 
49
#configure gettext using ENV Variable (setup during shutter start)
 
50
setlocale( LC_MESSAGES, "" );
 
51
my $d = Locale::gettext->domain("shutter-plugins");
 
52
$d->dir( $ENV{'SHUTTER_INTL'} );
 
53
 
 
54
#shutter will ask for some infos
 
55
my %plugin_info =       (       'name'  => $d->get( "barrel distortion" ),
 
56
                                                'sort'  => $d->get( "effect" ),
 
57
                                                'tip'   => $d->get("apply a distortion effect to your screenshot"),
 
58
                                        );
 
59
 
 
60
binmode( STDOUT, ":utf8" );
 
61
if ( exists $plugin_info{$ARGV[ 0 ]} ) {
 
62
        print $plugin_info{$ARGV[ 0 ]};
 
63
        exit;
 
64
}
 
65
 
 
66
#these variables are passed to the plugin
 
67
my $socket_id = $ARGV[ 0 ];
 
68
my $filename  = $ARGV[ 1 ];
 
69
my $width     = $ARGV[ 2 ];
 
70
my $height    = $ARGV[ 3 ];
 
71
my $filetype  = $ARGV[ 4 ];
 
72
 
 
73
#decode filename
 
74
utf8::decode $filename;
 
75
 
 
76
my $plug = Gtk2::Plug->new( $socket_id );
 
77
eval{
 
78
        $plug->set_default_icon_from_file( $ENV{'SHUTTER_ICON'} );
 
79
};
 
80
$plug->set_border_width( 10 );
 
81
 
 
82
$plug->signal_connect( destroy => sub { Gtk2->main_quit } );
 
83
 
 
84
#tooltips
 
85
my $tooltips = Gtk2::Tooltips->new;
 
86
 
 
87
#configure buttons and other needed controls
 
88
my $c1_label = Gtk2::Label->new( $d->get( "A:" ) );
 
89
my $c1_sbutton = Gtk2::SpinButton->new_with_range( -1, 1, 0.1 );
 
90
$c1_sbutton->set_value( 0.2 );
 
91
 
 
92
my $c2_label = Gtk2::Label->new( $d->get( "B:" ) );
 
93
my $c2_sbutton = Gtk2::SpinButton->new_with_range( -1, 1, 0.1 );
 
94
$c2_sbutton->set_value( 0 );
 
95
 
 
96
my $c3_label = Gtk2::Label->new( $d->get( "C:" ) );
 
97
my $c3_sbutton = Gtk2::SpinButton->new_with_range( -1, 1, 0.1 );
 
98
$c3_sbutton->set_value( 0 );
 
99
 
 
100
my $c4_label = Gtk2::Label->new( $d->get( "D:" ) );
 
101
my $c4_sbutton = Gtk2::SpinButton->new_with_range( -1, 1, 0.1 );
 
102
$c4_sbutton->set_value( 1.0 );
 
103
 
 
104
$tooltips->set_tip(
 
105
        $c1_label,
 
106
        $d->get(
 
107
                "The parameter d describes the linear scaling of the image. Using d=1, and a=b=c=0 leaves the image as it is. Choosing other d-values scales the image by that amount. a,b and c distort the image. Using negative values shifts distant points away from the center.\n\nDefined by Barrel Correction Distortion, by Helmut Dersch.\nhttp://www.all-in-one.ee/~dersch/barrel/barrel.html"
 
108
        )
 
109
);
 
110
 
 
111
$tooltips->set_tip(
 
112
        $c1_sbutton,
 
113
        $d->get(
 
114
                "The parameter d describes the linear scaling of the image. Using d=1, and a=b=c=0 leaves the image as it is. Choosing other d-values scales the image by that amount. a,b and c distort the image. Using negative values shifts distant points away from the center.\n\nDefined by Barrel Correction Distortion, by Helmut Dersch.\nhttp://www.all-in-one.ee/~dersch/barrel/barrel.html"
 
115
        )
 
116
);
 
117
 
 
118
$tooltips->set_tip(
 
119
        $c2_label,
 
120
        $d->get(
 
121
                "The parameter d describes the linear scaling of the image. Using d=1, and a=b=c=0 leaves the image as it is. Choosing other d-values scales the image by that amount. a,b and c distort the image. Using negative values shifts distant points away from the center.\n\nDefined by Barrel Correction Distortion, by Helmut Dersch.\nhttp://www.all-in-one.ee/~dersch/barrel/barrel.html"
 
122
        )
 
123
);
 
124
 
 
125
$tooltips->set_tip(
 
126
        $c2_sbutton,
 
127
        $d->get(
 
128
                "The parameter d describes the linear scaling of the image. Using d=1, and a=b=c=0 leaves the image as it is. Choosing other d-values scales the image by that amount. a,b and c distort the image. Using negative values shifts distant points away from the center.\n\nDefined by Barrel Correction Distortion, by Helmut Dersch.\nhttp://www.all-in-one.ee/~dersch/barrel/barrel.html"
 
129
        )
 
130
);
 
131
 
 
132
$tooltips->set_tip(
 
133
        $c3_label,
 
134
        $d->get(
 
135
                "The parameter d describes the linear scaling of the image. Using d=1, and a=b=c=0 leaves the image as it is. Choosing other d-values scales the image by that amount. a,b and c distort the image. Using negative values shifts distant points away from the center.\n\nDefined by Barrel Correction Distortion, by Helmut Dersch.\nhttp://www.all-in-one.ee/~dersch/barrel/barrel.html"
 
136
        )
 
137
);
 
138
 
 
139
$tooltips->set_tip(
 
140
        $c3_sbutton,
 
141
        $d->get(
 
142
                "The parameter d describes the linear scaling of the image. Using d=1, and a=b=c=0 leaves the image as it is. Choosing other d-values scales the image by that amount. a,b and c distort the image. Using negative values shifts distant points away from the center.\n\nDefined by Barrel Correction Distortion, by Helmut Dersch.\nhttp://www.all-in-one.ee/~dersch/barrel/barrel.html"
 
143
        )
 
144
);
 
145
 
 
146
$tooltips->set_tip(
 
147
        $c4_label,
 
148
        $d->get(
 
149
                "The parameter d describes the linear scaling of the image. Using d=1, and a=b=c=0 leaves the image as it is. Choosing other d-values scales the image by that amount. a,b and c distort the image. Using negative values shifts distant points away from the center.\n\nDefined by Barrel Correction Distortion, by Helmut Dersch.\nhttp://www.all-in-one.ee/~dersch/barrel/barrel.html"
 
150
        )
 
151
);
 
152
 
 
153
$tooltips->set_tip(
 
154
        $c4_sbutton,
 
155
        $d->get(
 
156
                "The parameter d describes the linear scaling of the image. Using d=1, and a=b=c=0 leaves the image as it is. Choosing other d-values scales the image by that amount. a,b and c distort the image. Using negative values shifts distant points away from the center.\n\nDefined by Barrel Correction Distortion, by Helmut Dersch.\nhttp://www.all-in-one.ee/~dersch/barrel/barrel.html"
 
157
        )
 
158
);
 
159
 
 
160
my $back_color_label = Gtk2::Label->new( $d->get("Background color"). ":" );
 
161
my $back_color = Gtk2::ColorButton->new();
 
162
$back_color->set_color( Gtk2::Gdk::Color->parse('gray') );
 
163
$back_color->set_alpha( int( 0 * 65535 ) );
 
164
$back_color->set_use_alpha(TRUE);
 
165
$back_color->set_title( $d->get("Choose background color") );
 
166
 
 
167
#all labels on the left side 
 
168
#need to have the same size
 
169
my $sgl = Gtk2::SizeGroup->new ('both');
 
170
$sgl->set ('ignore-hidden' => FALSE);
 
171
$sgl->add_widget($c1_label);
 
172
$sgl->add_widget($c2_label);
 
173
$sgl->add_widget($c3_label);
 
174
$sgl->add_widget($c4_label);
 
175
 
 
176
#we define two Gtk2::Image widgets
 
177
#to store the screenshot
 
178
#and a throbber that is shown while the changes are processed
 
179
my $preview =
 
180
        Gtk2::Image->new_from_pixbuf(
 
181
           Gtk2::Gdk::Pixbuf->new_from_file_at_scale( $filename, 300, 300, TRUE ) );
 
182
 
 
183
my $preview_throb =
 
184
        Gtk2::Image->new_from_file( $ENV{'SHUTTER_ROOT'}."/share/shutter/resources/icons/throbber.gif" );
 
185
 
 
186
my $sg = Gtk2::SizeGroup->new ('both');
 
187
$sg->set ('ignore-hidden' => FALSE);
 
188
$sg->add_widget($preview);
 
189
$sg->add_widget($preview_throb);
 
190
 
 
191
 
 
192
#we define three Gtk2::Button widgets
 
193
#to refresh, save and cancel the plugin's work
 
194
my $refresh_btn = Gtk2::Button->new_from_stock( 'gtk-refresh' );
 
195
$refresh_btn->signal_connect( 'clicked', \&fct_imagemagick_bardistortion,
 
196
                                                          'refresh' );
 
197
 
 
198
my $save_btn = Gtk2::Button->new_from_stock( 'gtk-save' );
 
199
$save_btn->signal_connect( 'clicked', \&fct_imagemagick_bardistortion, 'save' );
 
200
 
 
201
my $cancel_btn = Gtk2::Button->new_from_stock( 'gtk-cancel' );
 
202
$cancel_btn->signal_connect( 'clicked' => sub { Gtk2->main_quit; exit 2; }, 'cancel' );
 
203
 
 
204
#define the gui layout
 
205
my $hbox1      = Gtk2::HBox->new( FALSE, 8 );
 
206
my $hbox2      = Gtk2::HBox->new( FALSE, 8 );
 
207
my $hbox3      = Gtk2::HBox->new( FALSE, 8 );
 
208
my $hbox4      = Gtk2::HBox->new( FALSE, 8 );
 
209
my $hbox5      = Gtk2::HBox->new( FALSE, 8 );
 
210
 
 
211
my $hbox_row1 = Gtk2::HBox->new( TRUE, 8 );
 
212
my $hbox_row2 = Gtk2::HBox->new( FALSE, 8 );
 
213
 
 
214
my $vbox_param = Gtk2::VBox->new( FALSE,  8 );
 
215
my $vbox_left = Gtk2::VBox->new( FALSE, 8 );
 
216
my $vbox_right = Gtk2::VBox->new( FALSE, 8 );
 
217
 
 
218
my $hbox_btn  = Gtk2::HBox->new( TRUE,  8 );
 
219
my $vbox_btn  = Gtk2::VBox->new( FALSE, 8 );
 
220
my $vbox_main = Gtk2::VBox->new( FALSE, 8 );
 
221
 
 
222
#packing
 
223
$hbox1->pack_start( $c1_label, FALSE, TRUE, 5 );
 
224
$hbox1->pack_start( $c1_sbutton, TRUE,  TRUE, 5 );
 
225
 
 
226
$hbox2->pack_start( $c2_label, FALSE, TRUE, 5 );
 
227
$hbox2->pack_start( $c2_sbutton, TRUE,  TRUE, 5 );
 
228
 
 
229
$hbox3->pack_start( $c3_label, FALSE, TRUE, 5 );
 
230
$hbox3->pack_start( $c3_sbutton, TRUE,  TRUE, 5 );
 
231
 
 
232
$hbox4->pack_start( $c4_label, FALSE, TRUE, 5 );
 
233
$hbox4->pack_start( $c4_sbutton, TRUE,  TRUE, 5 );
 
234
 
 
235
$hbox5->pack_start( $back_color_label, FALSE, TRUE, 5 );
 
236
$hbox5->pack_start( $back_color, TRUE,  TRUE, 5 );
 
237
 
 
238
#row 1
 
239
$hbox_row1->pack_start_defaults( $hbox5 );
 
240
 
 
241
#controls on the left side
 
242
$vbox_left->pack_start_defaults( $hbox1 );
 
243
$vbox_left->pack_start_defaults( $hbox2 );
 
244
$vbox_left->pack_start_defaults( $hbox3 );
 
245
$vbox_left->pack_start_defaults( $hbox4 );
 
246
 
 
247
#preview
 
248
$vbox_right->pack_start_defaults( $preview );
 
249
$vbox_right->pack_start_defaults( $preview_throb );
 
250
 
 
251
#row 2
 
252
$hbox_row2->pack_start_defaults( $vbox_left );
 
253
$hbox_row2->pack_start_defaults( $vbox_right );
 
254
 
 
255
$vbox_param->pack_start( $hbox_row1, TRUE, TRUE, 5 );
 
256
$vbox_param->pack_start( $hbox_row2, TRUE, TRUE, 5 );
 
257
 
 
258
$vbox_main->pack_start( $vbox_param, FALSE, TRUE, 5 );
 
259
$vbox_main->pack_start( $refresh_btn, TRUE, TRUE, 5 );
 
260
 
 
261
$hbox_btn->pack_start( $cancel_btn, TRUE, TRUE, 5 );
 
262
$hbox_btn->pack_start( $save_btn,   TRUE, TRUE, 5 );
 
263
 
 
264
$vbox_main->pack_start( $hbox_btn,  TRUE, TRUE, 5 );
 
265
 
 
266
$plug->add( $vbox_main );
 
267
 
 
268
$plug->show_all;
 
269
 
 
270
#hide the preview widget at startup 
 
271
$preview->hide_all;
 
272
 
 
273
#create tempfile
 
274
my ( $tmpfh, $tmpfilename ) = tempfile();
 
275
#png format
 
276
$tmpfilename .= ".png";
 
277
 
 
278
#we fork a child process to do the work
 
279
my $process = Proc::Simple->new;
 
280
#create tempfiles for subprocess outputs
 
281
my ( $tmpfh_stdout, $tmpfilename_stdout ) = tempfile(UNLINK => 1);
 
282
my ( $tmpfh_stderr, $tmpfilename_sterr ) = tempfile(UNLINK => 1);
 
283
$process->redirect_output ($tmpfilename_stdout, $tmpfilename_sterr);
 
284
 
 
285
#generate first preview at startup
 
286
Glib::Idle->add (
 
287
        sub{
 
288
                &fct_imagemagick_bardistortion( undef, 'refresh' );
 
289
                return FALSE;   
 
290
        }, 
 
291
undef);
 
292
 
 
293
#lets'start
 
294
Gtk2->main;
 
295
 
 
296
sub fct_imagemagick_bardistortion {
 
297
        my ( $widget, $data ) = @_;
 
298
 
 
299
        $save_btn->set_sensitive(FALSE);
 
300
 
 
301
        if ( $data eq 'save' ) {
 
302
 
 
303
                my $image = Image::Magick->new;
 
304
                $image->ReadImage( $tmpfilename );
 
305
                $image->WriteImage( filename => $filename );
 
306
 
 
307
                #delete temp files
 
308
                unlink $tmpfilename;
 
309
 
 
310
                Gtk2->main_quit;
 
311
                return TRUE;
 
312
        } else {
 
313
 
 
314
                $preview->hide_all;
 
315
                $preview_throb->show_all;
 
316
 
 
317
                $process->start(
 
318
                        sub {
 
319
                                &apply_effect();
 
320
                                POSIX::_exit(0);
 
321
                        }
 
322
                );
 
323
 
 
324
                #so we can update the gui
 
325
                while ( $process->poll ) {
 
326
                        &fct_update_gui;
 
327
                        usleep 100000;
 
328
                }
 
329
                
 
330
                eval{           
 
331
                        $preview->set_from_pixbuf( Gtk2::Gdk::Pixbuf->new_from_file_at_scale(
 
332
                                                                                $tmpfilename, 300, 300, TRUE)
 
333
                                                                         );
 
334
                };
 
335
                #error -> read output from tempfiles
 
336
                if($@){         
 
337
                        #store error here
 
338
                        my $error_string = "Plugin error:\n";
 
339
                        
 
340
                        #reading stdout from file
 
341
                        while (<$tmpfh_stdout>){
 
342
                                $error_string .= $_;    
 
343
                        }
 
344
                        #reading stderr from file
 
345
                        while (<$tmpfh_stderr>){
 
346
                                $error_string .= $_;    
 
347
                        }
 
348
 
 
349
                        #get the parent window of the plug
 
350
                        require X11::Protocol;
 
351
                        my $x11 = X11::Protocol->new( $ENV{ 'DISPLAY' } );
 
352
                        
 
353
                        my $plugp = Gtk2::Gdk::Window->foreign_new( &find_wm_window( $x11, $plug->get_id ));
 
354
                        
 
355
                        #show error message
 
356
                        my $shutter_dialog = Shutter::App::SimpleDialogs->new($plug, $plugp);
 
357
                        $shutter_dialog->dlg_error_message( 
 
358
                                sprintf ( $d->get(  "Error while executing plugin %s." ), "'" . $plugin_info{'name'} . "'" ) ,
 
359
                                $d->get( "There was an error executing the plugin." ),
 
360
                                undef, undef, undef,
 
361
                                undef, undef, undef,
 
362
                                $error_string
 
363
                        );
 
364
                        
 
365
                        #delete temp files
 
366
                        unlink $tmpfilename;
 
367
 
 
368
                        Gtk2->main_quit;
 
369
                        exit 1; 
 
370
                }
 
371
 
 
372
                $save_btn->set_sensitive(TRUE);
 
373
                $preview->show_all;
 
374
                $preview_throb->hide_all;
 
375
 
 
376
                return TRUE;
 
377
        }
 
378
}
 
379
 
 
380
sub apply_effect {      
 
381
 
 
382
        my $color = $back_color->get_color;
 
383
 
 
384
        #execute imagemagick command            
 
385
        system(   "convert"
 
386
                        . " -virtual-pixel Background -background '"
 
387
                        . sprintf( "#%04x%04x%04x%04x", $color->red, $color->green, $color->blue, $back_color->get_alpha )
 
388
                        . "' -distort Barrel '"
 
389
                        . $c1_sbutton->get_value
 
390
                        . " "
 
391
                        . $c2_sbutton->get_value
 
392
                        . " "
 
393
                        . $c3_sbutton->get_value
 
394
                        . " "
 
395
                        . $c4_sbutton->get_value                                                                                                                
 
396
                        . "' '$filename'"
 
397
                        . " $tmpfilename" );
 
398
                                                                                                
 
399
}
 
400
 
 
401
sub fct_update_gui {
 
402
 
 
403
        while ( Gtk2->events_pending ) {
 
404
                Gtk2->main_iteration;
 
405
        }
 
406
        Gtk2::Gdk->flush;
 
407
 
 
408
        return TRUE;
 
409
}
 
410
 
 
411
sub find_wm_window {
 
412
        my $x11  = shift;
 
413
        my $xid  = shift;
 
414
 
 
415
        do {
 
416
                my ( $qroot, $qparent, @qkids ) = $x11->QueryTree($xid);
 
417
                return undef unless ( $qroot || $qparent );
 
418
                return $xid if ( $qroot == $qparent );
 
419
                $xid = $qparent;
 
420
        } while (TRUE);
 
421
}
 
422
 
 
423
1;