source: extensions/pLoader/trunk/src/Uploader/ImageList.pm @ 5184

Last change on this file since 5184 was 5184, checked in by ronosman, 14 years ago

Feature 1520 added : ability to set photo default caption after the photo is added.

  • Property svn:eol-style set to LF
File size: 39.0 KB
Line 
1# +-----------------------------------------------------------------------+
2# | pLoader - a Perl photo uploader for Piwigo                            |
3# +-----------------------------------------------------------------------+
4# | Copyright(C) 2008-2010 Piwigo Team                  http://piwigo.org |
5# +-----------------------------------------------------------------------+
6# | This program is free software; you can redistribute it and/or modify  |
7# | it under the terms of the GNU General Public License as published by  |
8# | the Free Software Foundation                                          |
9# |                                                                       |
10# | This program is distributed in the hope that it will be useful, but   |
11# | WITHOUT ANY WARRANTY; without even the implied warranty of            |
12# | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU      |
13# | General Public License for more details.                              |
14# |                                                                       |
15# | You should have received a copy of the GNU General Public License     |
16# | along with this program; if not, write to the Free Software           |
17# | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, |
18# | USA.                                                                  |
19# +-----------------------------------------------------------------------+
20package Uploader::ImageList;
21use strict;
22use Carp;
23use base qw/Uploader::Object/;
24use Image::ExifTool qw(:Public);
25use Image::Magick;
26use File::Spec;
27use Uploader::Image;
28use Data::Dumper;
29use Storable;
30use Digest::MD5::File qw/file_md5_hex md5_hex/;
31use Wx::Locale qw/:default/;
32use Wx qw/wxTheApp/;
33
34# this class implements a collection of image files with associated data
35$|=1;
36__PACKAGE__->mk_accessors( 
37    qw/
38                thumb_size
39                preview_ratio
40                categories
41                type
42                filter
43                blur
44                quality
45                resize_w
46                resize_h
47                hd_filter
48                hd_blur
49                hd_quality
50                hd_w
51                hd_h
52                hd_interlace
53                prefix
54                author
55                count
56                new_files
57                storable_file
58                wx_thumb_size
59                current_image
60                images
61                image_selection
62                exif_metadata
63                wx_thumb_imglist
64                wx_thumb_dir
65                site_resized_dir
66                site_thumb_dir
67                userdata_dir
68                progress_msg
69                last_error_msg
70                default_photo_name
71                default_photo_name_method
72                default_name_prefix
73                SetNewFilesViewerRefreshCallback
74                SetNewFilesProgressCallback
75                SetNewFilesDisplayEndInfoCallback
76                YieldCallback
77                UploadImagesViewerCallback
78                progress_thumbnail_refresh
79                progress_msg_details_refresh
80                progress_msg_refresh
81                progressbar_refresh
82                progress_endinfo_refresh
83                ResizeCallback
84                upload_rejects
85                pwg
86                upload_high
87                upload_hd
88                remove_uploaded_from_selection
89                wx_quality
90                th_quality
91                auto_rotate
92                interlace
93                create_resized
94                use_exif_preview
95                image_sums
96                upload_image_sums
97                sums
98                version
99                imagelist_version
100                uploaded_images
101                watermark_activate
102                watermark_activate_pwg_high
103                watermark_text
104                watermark_text_size
105                watermark_position
106                watermark_y
107                watermark_x
108                watermark_color
109                gravity
110                rgbcolor
111                upload_msg
112                upload_selection_count
113                upload_uploaded_count
114                upload_rejected_count
115                upload_last_error
116                upload_error_content
117                upload_begin_time
118                upload_end_time
119                upload_duration
120                upload_file
121                upload_name
122                ReuploadCallback
123                reupload_action_files
124                reupload_action_properties
125                reupload_action_properties_m
126                reupload_not_ask
127                display_mode
128                stop_processing
129                image_selection_tags
130                image_selection_privacy_level
131                image_selection_name
132                image_selection_comment
133                image_selection_author
134                image_selection_create_date
135     /
136);
137
138
139sub Init {
140    my ( $self ) = @_;
141   
142    $self->image_selection([]) if !defined $self->image_selection;
143    $self->uploaded_images([]);
144    $self->gravity(
145        { 
146            'Top'          => 'North',
147            'Left'         => 'West',
148            'Right'        => 'East',
149            'Bottom'       => 'South',
150            'Top left'     => 'NorthWest',
151            'Top right'    => 'NorthEast',
152            'Bottom left'  => 'SouthWest',
153            'Bottom right' => 'SouthEast',
154            'Center'       => 'Center',
155       }   
156    );   
157
158    $self->rgbcolor(
159        {
160            "White" => '#FFFFFF',
161            "Black" => '#000000',
162        }   
163    );
164   
165    $self->image_selection_tags(
166        []
167    ) unless defined $self->image_selection_tags;
168}
169
170sub _set_exif_tag {
171    my ( $self, $file, $tag, $newValue ) = @_;   
172
173  my $options = {};
174  # Create a new Image::ExifTool object
175  my $exifTool = new Image::ExifTool;
176
177  # Extract meta information from an image
178  $exifTool->ExtractInfo($file, $options);
179
180  # Set a new value for a tag
181  $exifTool->SetNewValue($tag, $newValue);
182
183  # Write new meta information to a file
184  $exifTool->WriteInfo($file);
185
186}
187
188
189sub _set_current_image_filepaths {
190    my ( $self ) = @_;
191
192    my $filename = sprintf(
193        "%s.%s",
194        $self->current_image->file_sum,
195        $self->type,
196    );
197
198
199    $self->current_image->wx_thumb_file( 
200        File::Spec->catfile(
201            $self->wx_thumb_dir,
202            $filename
203        )
204    );
205
206    $self->current_image->site_thumb_file( 
207        sprintf("%s.%s",
208            File::Spec->catfile(
209                $self->site_thumb_dir,
210                'thumbnail'
211            ),
212            $self->type
213        )
214    );
215
216}
217
218
219sub SetCurrentImage {
220    my ( $self, $indx ) = @_;   
221
222    $self->current_image(
223        $indx != -1 ? $self->GetImage($indx) : Uploader::Image->new()
224    );
225}
226
227
228sub SetNewFiles {
229    my ( $self, $files ) = @_;
230
231    $self->stop_processing(0);
232
233    $self->new_files( $files );
234
235    # if some files have been previously selected
236    my $i = scalar @{$self->sums};
237    #printf("SetNewFiles %s\n", $i);
238    my $count = 0;
239    $self->count($count);
240    my $errors = 0;
241
242    foreach my $file ( @{$files} ) {
243        my $info = $self->_read_exif_metatdata($file->{ANSIPathName});
244           my $is_new_image = $self->_add_image($file, $info, $i);   
245        $self->SetCurrentImage($i);
246        $self->_set_current_image_filepaths();
247
248        if($is_new_image){
249            #my $use_wx_resize = $self->_create_gui_preview($info);
250            $self->_create_gui_thumbnail();
251
252            # ok
253            if(!$@){
254                $self->progress_msg(gettext("Selection thumbnail created for %s"));
255            }
256            else {
257                $self->progress_msg("An error has occured when processing %s\n$@");
258                # remove from list
259                splice @{$self->sums}, $i, 1;
260                $errors++;
261            }
262       
263            $self->SetNewFilesProgressCallback->();
264        }
265        $i++;
266        $count++;
267        $self->count($count);
268        $self->SetNewFilesViewerRefreshCallback->();
269        last if $self->stop_processing;
270    }
271
272    $self->SetNewFilesDisplayEndInfoCallback->(
273        sprintf(
274            "%s : %s\n\n%s : %s",
275            gettext("photos added to the selection"),
276            $self->count,
277            gettext("errors"),
278            $errors,
279           
280        ),
281        $errors
282    );
283   
284    $self->Store;
285   
286}
287
288sub _read_exif_metatdata {
289    my ( $self, $file ) = @_;
290   
291    # read exif metadata
292    my $info;
293    eval {
294        $info = ImageInfo( $file );
295    };
296    $info = {} if($@);
297   
298    $info;
299}
300
301# key is file path
302sub _add_image {
303    my ( $self, $file, $info, $i ) = @_;   
304
305    my $is_new_image;
306
307    # for legacy imagelist that do not have image_sums property
308    $self->image_sums(
309        {}
310    ) if !$self->image_sums;
311
312    my $sum = file_md5_hex($file->{ANSIPathName});
313
314    my $image;
315    if ( !exists $self->image_sums->{$sum} ){
316        #print "_add_image ", Dumper $file, "\n";
317        # append to image list
318        $image = Uploader::Image->new(
319        {
320                file              => $file->{ANSIPathName},
321                file_sum          => $sum,
322                site_name         => $self->_default_photo_name($file->{PathName}, $info, $i),
323                site_author       => $self->author,
324                exif_metadata     => $self->_select_exif_data($info),
325                add_rank          => $i,
326                site_categories   => [],
327                site_tags         => [],
328                site_high_file    => $file->{ANSIPathName},
329            }
330        );
331
332        $self->image_sums->{$sum} = $image ;
333        $is_new_image = 1;
334    } else {
335        $image = $self->image_sums->{$sum};
336    }
337
338       
339    $self->sums->[$i] = $sum ;
340
341    $is_new_image;
342}
343
344sub GetCurrentImageDefaultName {
345    my ( $self, $index, $pattern ) = @_;
346
347    $pattern = wxTheApp->eng_default_photo_names->{$pattern};
348
349    $self->SetCurrentImage($index);
350
351    my $img = $self->current_image;
352
353    $self->_photo_name_from_pattern(
354        $img->file,
355        $img->create_date,
356        $index,
357        $pattern
358    );
359}
360
361sub _default_photo_name {
362    my ( $self, $file, $info, $i ) = @_;
363
364    my $create_date = $info->{CreateDate};
365   
366   
367    $self->_photo_name_from_pattern($file, $create_date, $i, $self->default_photo_name);
368}
369
370
371sub _photo_name_from_pattern {
372    my ( $self, $file, $create_date, $i, $pattern ) = @_;
373
374    my ( $yyyy, $mm, $dd, $hh, $mi, $ss ) = split /[:\s]/, $create_date ;
375 
376    my $chrono = join('', $yyyy, $mm, $dd);
377
378    my $name;
379    my $ext;
380    my ( $vol, $path, $filename ) = File::Spec->splitpath($file);
381    ( $filename, $ext ) = split /\.\w+$/, $filename;
382   
383
384    if('Prefix' eq $pattern){
385        $name = $self->default_name_prefix
386    }
387    elsif('File name' eq $pattern){
388        $name = $filename
389    }
390    elsif('File path and name' eq $pattern){
391        $name = sprintf(
392            "%s", 
393            File::Spec->catfile($path, $filename), 
394        )       
395    }   
396    elsif('Prefix + rank number' eq $pattern){
397        $name = sprintf(
398            "%s%s", 
399            $self->default_name_prefix, 
400            1+$i,
401        )       
402    }   
403    elsif('Rank number + prefix' eq $pattern){
404        $name = sprintf(
405            "%s%s", 
406            1+$i,
407            $self->default_name_prefix, 
408        )       
409    }   
410    elsif('Prefix + create date chrono' eq $pattern){
411        $name = sprintf(
412            "%s%s", 
413            $self->default_name_prefix, 
414            $chrono,
415        )       
416    }   
417    elsif('Create date chrono + prefix' eq $pattern){
418        $name = sprintf(
419            "%s%s", 
420            $chrono,
421            $self->default_name_prefix, 
422        )       
423    }
424
425    $name;
426}
427
428
429sub _create_gui_thumbnail {
430    my ( $self ) = @_;
431
432     eval {
433        if(!$self->CreateGUIThumbnail())
434        {
435            $self->ResizeCallback->(
436                $self->current_image->file,
437                $self->current_image->wx_thumb_file,
438                $self->type,
439                $self->wx_thumb_size,
440                $self->wx_thumb_size,
441                $self->wx_quality,
442            );
443           
444        }
445     };
446}
447
448sub RemoveImageSelection {
449    my ( $self ) = @_;
450   
451    return if (! scalar @{$self->sums} );
452    return if (! defined $self->image_selection );
453   
454    $self->_remove_image_list($self->image_selection);
455    # clear image selection
456    $self->image_selection([]);
457}
458
459sub _remove_image_list {
460    my ( $self, $list ) = @_;
461    # the list is sorted, ascendant
462    # we reverse it to have
463    # higher first, and keep same indexes during remove
464    @$list = reverse @$list;     
465    map {
466        $self->DeleteImage($_);
467        splice @{$self->sums}, $_, 1 ;
468        $self->wx_thumb_imglist->Remove($_);
469        shift @$list;
470    }
471    @$list;
472}
473
474
475# used for display in GUI. has to fit a square box ( wxImageList )
476sub CreateGUIThumbnail {
477    my ( $self ) = @_;
478
479    my $rval = 0;
480    my $image = new Image::Magick;
481
482    my $size = $self->wx_thumb_size||100;
483
484    my $status = $image->Set(size=>sprintf("%sx%s", 2*$size, 2*$size));
485    warn "$status" if $status ;
486
487    $status = $image->ReadImage(
488        $self->current_image->file
489    );
490    warn "$status" if $status;
491    return $rval if $status;
492
493    $self->current_image->width(
494        $image->Get('width')
495    );
496    $self->current_image->height(
497        $image->Get('height')
498    );
499
500
501    # maximize size and keep aspect ratio
502    $status = $image->Thumbnail(
503        geometry=>sprintf("%s%s>", $size*$size, '@')
504    );
505    # to get adjusted to a square box
506    #$status = $image->Thumbnail(
507    #    geometry=>sprintf("%sx%s%s", $size, $size, '^')
508    #);
509    warn "$status" if $status;
510    return $rval if $status;
511
512#    causes strange behaviour with i18n -> yellow borders when local is other than EN
513#    $status = $image->Set(background=>"white");
514#    warn "$status" if $status ;
515
516    $status = $image->Set(Gravity=>"Center");
517    warn "$status" if $status ;
518
519    $image->Extent(
520        geometry=>sprintf("%sx%s", $size, $size),
521        gravity=>'center',
522    );
523   
524    $image->Set(
525        quality=>$self->wx_quality||90
526    );
527
528    $status = $image->Strip();
529    warn "$status" if $status ;
530
531    # exif from original image
532    my $orientation = $self->current_image->exif_metadata->{Orientation};
533   
534    # Valid for Rotate 180, Rotate 90 CW, Rotate 270 CW
535    if( $orientation =~ m/Rotate (\d+)/ ){
536        printf(
537            "Rotate %s\n",
538            $1
539        );
540   
541        $image->Rotate( degrees=>$1 ) if $self->auto_rotate;   
542    }
543   
544
545    $image->Write(
546        sprintf(
547            "%s:%s",
548            $self->type,
549            $self->current_image->wx_thumb_file,
550        )
551    );
552
553    undef $image;
554   
555    $rval = 1;
556   
557    return $rval;
558}
559
560
561
562
563sub CreateResized {
564    my ( $self ) = @_;
565   
566    my $rval = 1 ;
567
568
569    my $image = new Image::Magick;
570
571    my $status = $image->ReadImage(
572        $self->current_image->file
573    );
574    warn "$status" if $status ;
575    return 0 if $status;
576
577    my $w = $image->Get('width');
578    my $h = $image->Get('height');
579
580    $status = $image->Set(Gravity=>"Center");
581    warn "$status" if $status ;
582
583    # exif from original image
584    my $orientation = $self->current_image->exif_metadata->{Orientation};
585   
586    # Valid for Rotate 180, Rotate 90 CW, Rotate 270 CW
587    if( $orientation =~ m/Rotate (\d+)/ ){
588        printf(
589            "Rotate %s\n",
590            $1
591        );
592   
593        $image->Rotate( degrees=>$1 ) if $self->auto_rotate;   
594    }
595
596
597    #printf("resize with blur value %s\n", $self->blur);
598    $status = $image->Resize(
599        geometry => sprintf("%sx%s>", $self->resize_w, $self->resize_h), 
600        filter => sprintf("%s", $self->filter), 
601        blur => $self->blur
602    );
603    warn "$status" if $status ;
604    return 0 if $status;
605
606    #printf("resize with quality value %s\n", $self->quality);
607    $status = $image->Set(quality=>$self->quality);
608    warn "$status" if $status ;
609
610    $status = $image->Set(interlace=>$self->interlace);
611    warn "$status" if $status ;
612
613    $image->Write(
614        sprintf(
615            "%s:%s",
616            $self->type,
617            $self->current_image->site_resized_file,
618        )
619    );
620    warn "$status" if $status ;
621    return 0 if $status;
622   
623    undef $image;
624
625   
626    $rval = 0 if $status;
627
628    return $rval;
629}
630
631sub CreateThumbnail {
632    my ( $self ) = @_;
633   
634    #return 1 if( -e $self->current_image->site_thumb_file );
635   
636    my $rval = 1;
637
638    my $image = new Image::Magick;
639
640    my $status = $image->ReadImage(
641        $self->current_image->site_resized_file
642    );
643    warn "$status" if $status ;
644
645   
646    $status = $image->Resize(
647        geometry => sprintf(
648                                "%sx%s>", 
649                                $self->thumb_size, 
650                                $self->thumb_size
651                           ),
652    );
653    warn "$status" if $status ;
654
655    $status = $image->Set(Gravity=>"Center");
656    warn "$status" if $status ;
657
658    $status = $image->Set(quality=>$self->th_quality);
659    warn "$status" if $status ;
660
661    $status = $image->Strip();
662    warn "$status" if $status ;
663
664
665    $image->Write(
666        sprintf(
667            "%s:%s",
668            $self->type,
669            $self->current_image->site_thumb_file,
670        )
671    );
672   
673    undef $image;
674
675
676    $rval = 0 if $status;
677
678    return $rval;
679}
680
681
682
683sub _select_exif_data {
684    my ( $self, $exif ) = @_;
685
686    return {
687        map {
688            $_ => $exif->{$_},
689        }
690        qw/
691            CreateDate
692            ImageWidth
693            ImageHeight
694            Orientation
695            DateTimeOriginal
696            ISO
697            ExposureTime
698            ApertureValue
699            FocalLength
700            Lens
701            Exposure
702            Make
703            Model
704        /
705    };   
706}
707
708sub Store {
709    my ( $self ) = @_;
710   
711    my $data = $self->get_storable(
712        [ 
713            qw/
714                images
715                thumb_size
716                preview_ratio
717                type
718                filter
719                blur
720                quality
721                wx_quality
722                th_quality
723                prefix
724                author
725                count
726                resize_w
727                resize_h
728                hd_filter
729                hd_blur
730                hd_quality
731                hd_w
732                hd_h
733                hd_interlace
734                new_files
735                storable_file
736                wx_thumb_size
737                current_image
738                exif_metadata
739                wx_thumb_dir
740                site_resized_dir
741                site_thumb_dir
742                userdata_dir
743                progress_msg
744                default_photo_name
745                default_name_prefix
746                upload_high
747                upload_hd
748                remove_uploaded_from_selection
749                auto_rotate
750                interlace
751                create_resized
752                use_exif_preview
753                image_sums
754                sums
755                version
756                imagelist_version
757                watermark_activate
758                watermark_activate_pwg_high
759                watermark_text
760                watermark_text_size
761                watermark_position
762                watermark_y
763                watermark_x
764                watermark_color
765                reupload_action_files
766                reupload_action_properties
767                reupload_action_properties_m
768                display_mode
769                image_selection_tags
770            /
771        ] 
772   
773    );
774    eval {
775        store $data, $self->storable_file;
776    };
777    if($@){
778        print $@, "\n";   
779    }
780}
781
782
783
784sub UploadSelection {
785    my ( $self ) = @_;
786
787    $self->stop_processing(0);
788
789    my $viewer_callback = $self->UploadImagesViewerCallback ;
790
791    $self->image_selection([]) if !defined $self->image_selection;
792    $self->upload_rejects(
793        []
794    );
795
796    $self->count(
797        1
798    );
799
800    $self->upload_uploaded_count(0);
801    $self->upload_rejected_count(0);
802    $self->upload_begin_time(time);
803    $self->upload_selection_count(scalar @{$self->image_selection});
804    # for re-upload management
805    $self->upload_image_sums( [
806            map { $self->GetImage($_)->file_sum }
807            @{$self->image_selection}
808        ] 
809    );
810
811    # check if already exist on server
812    my $uploaded = $self->pwg->IsAlreadyUploaded($self->upload_image_sums);
813    my @already_uploaded = grep { $_ } values %$uploaded ; 
814    $self->ReuploadCallback->() if ( scalar @already_uploaded and !$self->reupload_not_ask );
815
816   
817    foreach(@{$self->image_selection}) {
818    # current image object       
819        $self->current_image(
820            $self->GetImage($_)
821        ); 
822        # prepare resized, high, thumbnail
823        # if not already uploaded
824        $self->_set_site_resized_file();
825        $self-> _set_site_high_file ();
826        # photo metadata
827        $self->_upload_selection_prepare() if (!$uploaded->{$self->current_image->file_sum} or $self->reupload_action_files);
828        $self->_prepare_upload_properties();       
829
830        # transfert resized, high, thumbnail to site
831        my $status = $self->_upload_selection_transfert();
832        # log operations
833        $self->_upload_selection_log($status);
834        $self->count(
835            1+$self->count
836        );
837        # remove thumbnail, resized
838        # to make sure everything is clean
839        # keep site_high_file because it can be the original !!!
840        $self->_remove_resized_from_cache;
841
842        last if $self->stop_processing;
843    }
844
845    $self->stop_processing(0);
846
847    if($self->remove_uploaded_from_selection){
848        $self->_remove_image_list($self->uploaded_images);
849        # clear thumbnail imagelistctrl
850        $viewer_callback->();
851    }
852
853    $self->_upload_selection_final_log();
854
855}
856
857
858sub _remove_resized_from_cache {
859    my ( $self ) = @_;
860
861    unlink $self->current_image->site_thumb_file if -e $self->current_image->site_thumb_file;
862
863    map {
864        my $file = File::Spec->catfile(
865            $self->site_resized_dir,
866            sprintf(
867                "%s.%s",
868                 $_,
869                $self->type,
870            )
871        );
872        unlink $file if -e $file;
873    } qw /resized high/;
874
875
876}
877
878sub _upload_selection_prepare {
879    my ( $self ) = @_;
880
881    $self->progress_thumbnail_refresh->();
882    # PREPARE
883    $self->_set_upload_msg(gettext("Preparing resized image for"));
884    $self->_upload_progress();
885    #printf("resized %s\n", $self->create_resized);
886    if( $self->create_resized ){
887        $self->_create_site_resized_file();
888        $self->_set_upload_msg(gettext("Resized image done for"));
889        $self->_upload_progress();
890    }
891    # the original is at the right size, no need to create a resize
892    else {
893        #printf("original no resized %s\n", $self->create_resized);
894        $self->current_image->site_resized_file(
895            $self->current_image->file,
896        );
897    }
898
899    my $decode = {
900        'No' => 0,
901        'Yes, use HD resized of the original photo' => 'HD',
902        'Yes, use a copy of the original photo' => 'ORIGINAL',
903    };   
904    #printf("upload HD %s\n", $self->upload_hd);
905    $self->upload_high(
906        $decode->{$self->upload_hd}
907    );
908    #printf("upload High %s\n", $self->upload_high);
909   
910    # if upload high, rotate a copy of original file
911    if($self->upload_high){
912        $self->CreateHigh();
913        $self->_set_upload_msg(gettext("HD image done for"));
914        $self->_upload_progress();
915    }
916
917    eval {
918        $self->CreateThumbnail();
919    };
920    $self->_set_upload_msg(gettext("Thumbnail image done for"));
921    $self->_upload_progress();
922
923
924}
925
926sub _upload_progress {
927    my ( $self, $value ) = @_;
928
929    eval {
930        $self->progress_msg_refresh->(
931            $self->upload_msg
932        );
933    };
934    # user cancelled : dialog box is destroyed
935    croak gettext("Upload cancelled"), " .", $@ if $@ ;
936
937
938}
939
940sub _set_upload_msg {
941    my ( $self, $msg, $errmsg ) = @_;
942
943    $self->upload_msg(
944        sprintf(
945            "%s : %s - %s\n\n%s %s %s %s\n%s",
946            $msg,
947            $self->upload_file,
948            $self->upload_name,
949            gettext("Photo"),
950            $self->count,
951            gettext("on"),
952            $self->upload_selection_count,
953            $errmsg
954        )
955    );
956}
957
958sub _upload_selection_transfert {
959    my ( $self ) = @_;
960
961    return if $self->stop_processing;
962
963    $self->_set_upload_msg(gettext("Uploading"));
964    $self->_upload_progress(0);
965
966    # UPLOAD
967    my ( $status, $status_msg, $content ) = $self->pwg->UploadImage(
968        { 
969            yield           => $self->YieldCallback, 
970            bar             => $self->progressbar_refresh, 
971            msg             => $self->progress_msg_refresh,
972            msg_details     => $self->progress_msg_details_refresh,
973            resized_msg     => gettext("Uploading resized"),
974            thumbnail_msg   => gettext("Uploading thumbnail"),
975            highdef_msg     => gettext("Uploading high definition"),
976            checksum_msg    => gettext("Checksum for"),
977            original_sum    => $self->current_image->file_sum,
978            stop_processing => $self->stop_processing,
979        } 
980    );
981    my $ok = 0;
982    # HTTP REQUEST OK
983    if ( $status ){
984        # PIWIGO RESULT ( HTTP may be ok while Piwigo is not )
985        $ok = 'fail' eq $content->{stat} ? 0 : 1;
986    }
987    else{
988        Wx::LogMessage(
989            "%s %s : %s",
990            gettext("Communication error with"),
991            $self->pwg->site_url,
992            $status_msg,
993        );
994    }
995    $self->upload_last_error(
996        $status_msg
997    );
998
999    $self->upload_error_content(
1000        $content
1001    );
1002
1003    $ok;
1004}
1005
1006sub _upload_selection_log {
1007    my ( $self, $ok ) = @_;
1008
1009    if($ok){
1010        $self->_set_upload_msg(gettext("Uploaded"));
1011        $self->_upload_progress(0);
1012        push @{$self->uploaded_images}, $_;
1013        $self->upload_uploaded_count(
1014            1+$self->upload_uploaded_count       
1015        );
1016    } else {
1017        $self->_set_upload_msg(gettext("An error has occured"), Dumper($self->upload_error_content));
1018        $self->upload_rejected_count(
1019            1+$self->upload_rejected_count
1020        );
1021    }   
1022       
1023}
1024
1025sub _upload_selection_final_log {
1026    my ( $self ) = @_;
1027
1028    $self->upload_end_time(time);
1029    $self->upload_duration(
1030        $self->upload_end_time - $self->upload_begin_time
1031    );
1032
1033    $self->progress_endinfo_refresh->(
1034        sprintf(
1035            "%s : %s\n\n%s : %s\n\n%s : %s\n\n\n%s : %s %s",
1036            gettext("images processed"),
1037            $self->count - 1,
1038            gettext("images uploaded"),
1039            $self->upload_uploaded_count,
1040            gettext("images in errors and not uploaded"),
1041            $self->upload_rejected_count,
1042            gettext("Duration"),
1043            $self->upload_duration,
1044            gettext("seconds"),
1045        )
1046    );
1047}
1048
1049sub _set_site_resized_file {
1050    my ( $self ) = @_;
1051
1052    my ( $vol, $dir, $file ) = File::Spec->splitpath(
1053        $self->current_image->file
1054    );
1055
1056    $self->upload_file(
1057        $file
1058    );
1059       
1060    $self->upload_name(
1061        $self->current_image->site_name
1062    );
1063    my $filename = $self->current_image->file_sum ;
1064
1065    # lately defined to make sure we have the last global properties ( resize_w, resize_h )
1066    $self->current_image->site_resized_file( 
1067        File::Spec->catfile(
1068            $self->site_resized_dir,
1069            sprintf(
1070                "%s.%s",
1071                'resized',
1072                $self->type,
1073            )
1074        )
1075    );
1076    printf("_set_site_resized_file %s\n", $self->current_image->site_resized_file);
1077}
1078
1079sub _create_site_resized_file {
1080    my ( $self ) = @_;
1081
1082    eval {
1083        if(!$self->CreateResized()){
1084            $self->_create_resized_fallback();
1085        };
1086
1087        $self->_set_exif_tag(
1088            $self->current_image->site_resized_file,
1089            'Orientation',
1090            'Horizontal (normal)',
1091        ) if $self->auto_rotate;
1092
1093        $self->CreateWatermark(
1094            $self->watermark_text,
1095            $self->watermark_text_size,
1096            $self->watermark_position,
1097            $self->watermark_x,
1098            $self->watermark_y,
1099            $self->watermark_color,
1100            $self->current_image->site_resized_file
1101        ) if $self->watermark_activate;
1102    }
1103}
1104
1105sub _create_resized_fallback {
1106    my ( $self ) = @_;
1107    # use wx builtin rescale if IM fails
1108    printf("CreateResized failed %s. Use ResizeCallback\n", $@);
1109    # use method provided by the caller
1110    # source, target, type, ratio, width, $height
1111    $self->ResizeCallback->(
1112        $self->current_image->file,
1113        $self->current_image->site_resized_file,
1114        $self->type,
1115        $self->resize_w,
1116        $self->resize_h,
1117        $self->quality,
1118    );
1119               
1120    $self->RotateImage(
1121        $self->current_image->site_resized_file,
1122    ) if $self->auto_rotate;
1123}
1124
1125# if we need to rotate
1126sub CreateHigh {
1127    my ( $self ) = @_;
1128
1129    #printf("CreateHigh %s\n", $self->upload_high);
1130    my $bModifyOriginal;
1131    my $bRotate;
1132    my $bAddWatermark;
1133    my $bResize;
1134    my $orientation = $self->current_image->exif_metadata->{Orientation};
1135    my $degrees;
1136   
1137    # Valid for Rotate 180, Rotate 90 CW, Rotate 270 CW
1138    if( $self->auto_rotate and $orientation =~ m/Rotate (\d+)/ ){
1139        $bModifyOriginal = 1;
1140        $bRotate = 1;
1141        $degrees = $1;
1142    }
1143
1144    if( $self->watermark_activate_pwg_high ){
1145        $bModifyOriginal = 1;
1146        $bAddWatermark = 1;
1147    }
1148   
1149    # HD resize
1150    if('HD' eq $self->upload_high){
1151        $bModifyOriginal = 1;
1152        $bResize = 1;
1153    }
1154
1155    if($bModifyOriginal){
1156
1157        my $image = Image::Magick->new();
1158        # we read original
1159        my $status = $image->Read(
1160            $self->current_image->file
1161        );
1162        warn "$status ", $self->current_image->file, "\n" if $status ;
1163        return 0 if $status;
1164
1165        if($bRotate){
1166            $image->Rotate( degrees=>$degrees );   
1167        }       
1168        $image->Write(
1169            $self->current_image->site_high_file
1170        );
1171        warn "$status ", $self->current_image->site_high_file, "\n" if $status ;
1172        return 0 if $status;
1173
1174        if($bResize){
1175            $status = $image->Resize(
1176                geometry => sprintf("%sx%s>", $self->hd_w, $self->hd_h), 
1177                filter => sprintf("%s", $self->hd_filter), 
1178                blur => $self->hd_blur
1179            );
1180            warn "$status" if $status ;
1181            return 0 if $status;
1182        }
1183       
1184        #printf("resize with quality value %s\n", $self->quality);
1185        $status = $image->Set(quality=>$self->quality);
1186        warn "$status" if $status ;
1187
1188        $status = $image->Set(interlace=>$self->interlace);
1189        warn "$status" if $status ;
1190       
1191       
1192        undef $image;
1193
1194        if($bAddWatermark){
1195          my $file_out = $self->current_image->site_high_file;
1196          $self->CreateWatermark(
1197             $self->watermark_text,
1198                $self->watermark_text_size,
1199                $self->watermark_position,
1200                $self->watermark_x,
1201                $self->watermark_y,
1202                $self->watermark_color,
1203                $file_out
1204            );
1205        }
1206
1207
1208        $self->_set_exif_tag(
1209            $self->current_image->site_high_file,
1210            'Orientation',
1211            'Horizontal (normal)',
1212        );
1213
1214        # Now all images that need to be rotated are done. Update exif
1215        $self->current_image->exif_metadata->{Orientation} = 'Horizontal (normal)';
1216
1217
1218    }
1219    else{
1220        # high file is the original file
1221        $self->current_image->site_high_file(
1222            $self->current_image->file
1223        );
1224        #printf("site high file %s\n", $self->current_image->site_high_file);
1225    }
1226
1227    return 1;
1228}
1229
1230# file name for original copy
1231# we do not need the original file name
1232sub _set_site_high_file {
1233        my ( $self ) = @_;
1234
1235        my ( $vol, $dir, $file ) = File::Spec->splitpath(
1236            $self->current_image->file
1237        );
1238       
1239        $self->current_image->site_original_filename(
1240            $file
1241        );
1242        my ( $filename, $ext ) = split /\./, $file ;
1243   
1244        # high_file is a resized of original
1245        $self->current_image->site_high_file( 
1246            File::Spec->catfile(
1247                $self->site_resized_dir,
1248                sprintf(
1249                    "%s.%s",
1250                     'high',
1251                    $self->type,
1252                )
1253            )
1254        );
1255}
1256
1257
1258
1259sub CreateWatermark {
1260    my ( $self, $text, $text_size, $position, $x, $y, $color, $file_out ) = @_;
1261   
1262    my $rval = 1 ;
1263    my $gravity = $self->gravity->{$position};
1264    my $fill = $self->rgbcolor->{$color};
1265
1266    # debug
1267    #printf("Create watermark %s\n", $file_out);
1268
1269   
1270
1271    my $image = new Image::Magick;
1272   
1273    my $status = $image->ReadImage(
1274        $file_out
1275    );     
1276
1277    my $ratio = $image->Get('height')/($self->resize_h||$image->Get('height'));
1278    $ratio||=1;
1279    $text ||="Your watermark";
1280    $image->Annotate(
1281        pointsize => $text_size*$ratio,
1282        fill => $fill,
1283        x => $x*$ratio,
1284        y => $y*$ratio,
1285        text => $text,
1286        gravity => $gravity,
1287    );
1288                     
1289    $image->Write(
1290        sprintf(
1291            "%s:%s",
1292            $self->type,
1293            $file_out,
1294        )
1295    );
1296}
1297
1298sub _prepare_upload_properties {
1299    my ( $self ) = @_;
1300
1301    # set default values only if not defined
1302    # || operator is not used because 0 is a choice value
1303    # and would replace a valid choice with a default value
1304    $self->reupload_action_files(1) 
1305        unless defined $self->reupload_action_files;
1306
1307    $self->pwg->reupload_action_properties(1)
1308        unless defined $self->pwg->reupload_action_properties;
1309
1310    $self->pwg->reupload_action_properties_m(1)
1311        unless defined $self->pwg->reupload_action_properties_m;
1312
1313    $self->pwg->reupload_action_files(
1314        $self->reupload_action_files
1315    );
1316    $self->pwg->reupload_action_properties(
1317        $self->reupload_action_properties
1318    );
1319
1320    $self->pwg->reupload_action_properties_m(
1321        $self->reupload_action_properties_m
1322    );
1323   
1324    $self->pwg->upload_high(
1325        $self->upload_high
1326    );
1327
1328    $self->pwg->site_high_file(
1329        $self->current_image->site_high_file
1330    );
1331
1332    $self->pwg->site_original_filename(
1333        $self->current_image->site_original_filename
1334    );
1335
1336
1337    $self->pwg->site_resized_file(
1338        $self->current_image->site_resized_file
1339    );
1340
1341    $self->pwg->site_thumb_file(
1342        $self->current_image->site_thumb_file
1343    );
1344
1345    $self->pwg->site_author(
1346        $self->current_image->site_author
1347    );
1348
1349    $self->pwg->site_comment(
1350        $self->current_image->site_comment
1351    );
1352
1353    $self->pwg->site_image_name(
1354        $self->current_image->site_name
1355    );
1356
1357    $self->pwg->site_img_date_creation(
1358        substr($self->current_image->create_date, 0, 10)
1359    );
1360
1361    $self->pwg->privacy_level(
1362        $self->current_image->privacy_level
1363    );
1364   
1365    $self->current_image->site_categories(
1366        $self->categories
1367    );
1368
1369    $self->pwg->categories(
1370        sprintf(
1371            "%s",
1372            join(';', @{$self->categories})
1373        )
1374    );
1375
1376    $self->pwg->site_tags(
1377        join(',', @{$self->current_image->site_tags})
1378    );
1379
1380   
1381}
1382
1383# read Orientation exif tag from original image
1384# apply rotation to $file image
1385sub RotateImage {
1386    my ( $self, $file ) = @_;
1387   
1388    # exif from original image
1389    my $orientation = $self->current_image->exif_metadata->{Orientation};
1390
1391    # Valid for Rotate 180, Rotate 90 CW, Rotate 270 CW
1392    if( $orientation =~ m/Rotate (\d+)/ ){
1393        printf(
1394            "Rotate %s\n",
1395            $1
1396        );
1397
1398        my $image = Image::Magick->new();
1399       
1400        # read resized file
1401        my $status = $image->Read(
1402            $file
1403        );
1404        warn "$status ", $file, "\n" if $status ;
1405        return 0 if $status;
1406   
1407        $image->Rotate( degrees=>$1 );   
1408       
1409        # write resized file
1410        $image->Write(
1411            $file
1412        );
1413        warn "$status ", $file, "\n" if $status ;
1414        return 0 if $status;
1415       
1416        undef $image;
1417   
1418    }   
1419    return 1;
1420}
1421
1422sub GetImage {
1423    my ( $self, $indx ) = @_;
1424   
1425    my $sum = $self->sums->[$indx];
1426
1427    $self->image_sums->{$sum};
1428}
1429
1430sub DeleteImage {
1431    my ( $self, $indx ) = @_;
1432   
1433    my $sum = $self->sums->[$indx];
1434
1435    delete $self->image_sums->{$sum};
1436}
1437
1438sub multi_selection_mode {
1439    my ( $self ) = @_;
1440
1441    scalar @{$self->image_selection} > 1;
1442}
1443
1444
1445sub SetImageSelectionTags {
1446    my ( $self, $tags ) = @_;
1447
1448    $self->image_selection_tags($tags) if 'ARRAY' eq ref $tags;
1449
1450    # append to each image
1451    # if multiple selection
1452    if($self->multi_selection_mode){
1453        map {
1454            # need to dedup
1455            my $tags = [
1456                @{$self->GetImage($_)->site_tags},
1457                @{$self->image_selection_tags},
1458            ];
1459            #deduplicate
1460            my $uniq = {
1461                 map { $_ => 1 } @$tags
1462            };
1463            @$tags = keys %$uniq;
1464            $self->GetImage($_)->site_tags(
1465                $tags
1466            );
1467        }@{$self->image_selection};
1468    }
1469
1470    $self->image_selection_tags;
1471}
1472
1473
1474sub SetImageSelectionPrivacyLevel {
1475    my ( $self, $privacy_level ) = @_;
1476
1477    # append to each image
1478    # if multiple selection
1479    if($self->multi_selection_mode){
1480        if(defined $privacy_level){
1481            $self->image_selection_privacy_level($privacy_level);
1482            map {
1483                $self->GetImage($_)->privacy_level(
1484                    $privacy_level
1485                ) ;
1486            }@{$self->image_selection}
1487        };
1488    }
1489
1490    $self->image_selection_privacy_level;
1491}
1492
1493
1494sub SetImageSelectionName {
1495    my ( $self, $name, $param ) = @_;
1496   
1497    # works in single and multi selection mode
1498    if(defined $name){
1499        map {
1500            my $_name = 'CODE' eq ref $name ?
1501                $name->($_, $param) :
1502                $name;
1503            $self->image_selection_name($_name);
1504
1505            $self->GetImage($_)->site_name(
1506                $_name
1507            ) ;
1508        }@{$self->image_selection}
1509    }
1510}
1511
1512sub SetImageSelectionAuthor {
1513    my ( $self, $author ) = @_;
1514
1515    # append to each image
1516    # if multiple selection
1517    if($self->multi_selection_mode){
1518        if(defined $author){
1519            $self->image_selection_author($author);
1520            map {
1521                $self->GetImage($_)->site_author(
1522                    $author
1523                ) ;
1524            }@{$self->image_selection}
1525        };
1526    }
1527
1528    $self->image_selection_author;
1529}
1530
1531sub SetImageSelectionComment {
1532    my ( $self, $comment ) = @_;
1533
1534    # append to each image
1535    # if multiple selection
1536    if($self->multi_selection_mode){
1537        if(defined $comment){
1538            $self->image_selection_comment($comment);
1539            map {
1540                $self->GetImage($_)->site_comment(
1541                    $comment
1542                ) ;
1543            }@{$self->image_selection}
1544        };
1545    }
1546
1547    $self->image_selection_comment;
1548}
1549
1550
1551sub SetImageSelectionCreateDate {
1552    my ( $self, $date ) = @_;
1553
1554    # append to each image
1555    # if multiple selection
1556    if($self->multi_selection_mode){
1557        if(defined $date){
1558            $self->image_selection_create_date($date);
1559            map {
1560                $self->GetImage($_)->create_date(
1561                    $date
1562                ) ;
1563            }@{$self->image_selection}
1564        };
1565    }
1566
1567    $self->image_selection_create_date;
1568}
1569
15701;
Note: See TracBrowser for help on using the repository browser.