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

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

Bug 1288 fixed : photo create date read from exif may be with a bad format.

  • Property svn:eol-style set to LF
File size: 31.6 KB
Line 
1# +-----------------------------------------------------------------------+
2# | pLoader - a Perl photo uploader for Piwigo                            |
3# +-----------------------------------------------------------------------+
4# | Copyright(C) 2008      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;
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                prefix
46                author
47                count
48                resize_w
49                resize_h
50                new_files
51                storable_file
52                wx_thumb_size
53                current_image
54                images
55                image_selection
56                exif_metadata
57                wx_thumb_imglist
58                wx_thumb_dir
59                site_resized_dir
60                site_thumb_dir
61                userdata_dir
62                progress_msg
63                last_error_msg
64                default_photo_name
65                default_photo_name_method
66                default_name_prefix
67                SetNewFilesViewerRefreshCallback
68                SetNewFilesProgressCallback
69                SetNewFilesDisplayEndInfoCallback
70                YieldCallback
71                UploadImagesViewerCallback
72                progress_thumbnail_refresh
73                progress_msg_details_refresh
74                progress_msg_refresh
75                progressbar_refresh
76                progress_endinfo_refresh
77                RescaleCallback
78                ResizeCallback
79                upload_rejects
80                pwg
81                upload_high
82                remove_uploaded_from_selection
83                wx_quality
84                th_quality
85                auto_rotate
86                interlace
87                create_resized
88                use_exif_preview
89                image_sums
90                sums
91                version
92                imagelist_version
93                uploaded_images
94                watermark_activate
95                watermark_activate_pwg_high
96                watermark_text
97                watermark_text_size
98                watermark_position
99                watermark_y
100                watermark_x
101                watermark_color
102                gravity
103                rgbcolor
104                upload_msg
105                upload_selection_count
106                upload_uploaded_count
107                upload_rejected_count
108                upload_last_error
109                upload_error_content
110                upload_begin_time
111                upload_end_time
112                upload_duration
113                upload_file
114                upload_name
115     /
116);
117
118
119sub Init {
120    my ( $self ) = @_;
121   
122    $self->uploaded_images([]);
123    $self->gravity(
124        { 
125            'Top'          => 'North',
126            'Left'         => 'West',
127            'Right'        => 'East',
128            'Bottom'       => 'South',
129            'Top left'     => 'NorthWest',
130            'Top right'    => 'NorthEast',
131            'Bottom left'  => 'SouthWest',
132            'Bottom right' => 'SouthEast',
133            'Center'       => 'Center',
134       }   
135    );   
136
137    $self->rgbcolor(
138        {
139            "White" => '#FFFFFF',
140            "Black" => '#000000',
141        }   
142    );
143   
144}
145
146
147
148# save exif preview image if available
149# otherwise create a preview image
150sub _write_preview_image {
151    my ( $self, $imagedata ) = @_;
152
153
154    # If PreviewImage is available, we use it
155    if(defined $imagedata ) {
156        print "_write_preview_image, use exif PreviewImage\n";
157        eval {
158            open PREVIEW_FILE, ">", $self->current_image->preview_file ;
159            binmode PREVIEW_FILE;
160            print PREVIEW_FILE $$imagedata;
161            close PREVIEW_FILE;
162        };
163        $self->last_error_msg($@) if $@;
164    }
165   
166}
167
168
169sub _set_exif_tag {
170    my ( $self, $file, $tag, $newValue ) = @_; 
171
172  my $options = {};
173  # Create a new Image::ExifTool object
174  my $exifTool = new Image::ExifTool;
175
176  # Extract meta information from an image
177  $exifTool->ExtractInfo($file, $options);
178
179  # Set a new value for a tag
180  $exifTool->SetNewValue($tag, $newValue);
181
182  # Write new meta information to a file
183  $exifTool->WriteInfo($file);
184
185}
186
187
188sub _set_current_image_filepaths {
189    my ( $self ) = @_;
190
191    my $filename = sprintf(
192        "%s.%s",
193        $self->current_image->file_sum,
194        $self->type,
195    );
196
197
198    $self->current_image->wx_thumb_file( 
199        File::Spec->catfile(
200            $self->wx_thumb_dir,
201            $filename
202        )
203    );
204
205    $self->current_image->site_thumb_file( 
206        File::Spec->catfile(
207            $self->site_thumb_dir,
208            $filename
209        )
210    );
211
212}
213
214
215sub SetCurrentImage {
216    my ( $self, $indx ) = @_;   
217
218    $self->current_image(
219        $self->GetImage($indx)
220    );
221}
222
223
224sub SetNewFiles {
225    my ( $self, $files ) = @_;
226
227    $self->new_files( $files );
228
229    # if some files have been previously selected
230    my $i = scalar @{$self->sums};
231printf("SetNewFiles %s\n", $i);
232    my $count = 0;
233    $self->count($count);
234    my $errors = 0;
235
236    map {
237        my $info = $self->_read_exif_metatdata($_->{ANSIPathName});
238        my $is_new_image = $self->_add_image($_, $info, $i);   
239        $self->SetCurrentImage($i);
240        $self->_set_current_image_filepaths();
241
242        if($is_new_image){
243            #my $use_wx_resize = $self->_create_gui_preview($info);
244            $self->_create_gui_thumbnail();
245
246            # ok
247            if(!$@){
248                $self->progress_msg("Selection thumbnail created for %s");
249            }
250            else {
251                $self->progress_msg("An error has occured when processing %s\n$@");
252                # remove from list
253                splice @{$self->sums}, $i, 1;
254                $errors++;
255            }
256       
257            $self->SetNewFilesProgressCallback->();
258        }
259        $i++;
260        $count++;
261        $self->count($count);
262        $self->SetNewFilesViewerRefreshCallback->();
263    }
264    @{$files};
265    $self->SetNewFilesDisplayEndInfoCallback->(
266        sprintf(
267            "%s : %s\n\n%s : %s",
268            gettext("photos added to the selection"),
269            $self->count,
270            gettext("errors"),
271            $errors,
272           
273        )
274    );
275   
276    $self->Store;
277   
278}
279
280sub _read_exif_metatdata {
281    my ( $self, $file ) = @_;
282   
283    # read exif metadata
284    my $info;
285    eval {
286        $info = ImageInfo( $file );
287    };
288    $info = {} if($@);
289   
290    $info;
291}
292
293# key is file path
294sub _add_image {
295    my ( $self, $file, $info, $i ) = @_;       
296
297    my $is_new_image;
298
299    # for legacy imagelist that do not have image_sums property
300    $self->image_sums(
301        {}
302    ) if !$self->image_sums;
303
304    my $sum = file_md5_hex($file->{ANSIPathName});
305
306    my $image;
307    if ( !exists $self->image_sums->{$sum} ){
308        #print "_add_image ", Dumper $file, "\n";
309        # append to image list
310        $image = Uploader::Image->new(
311        {
312                file              => $file->{ANSIPathName},
313                file_sum          => $sum,
314                site_name         => $self->_default_photo_name($file->{PathName}, $info, $i),
315                site_author       => $self->author,
316                exif_metadata     => $self->_select_exif_data($info),
317                add_rank          => $i,
318                site_categories   => [],
319                site_tags         => [],
320                site_high_file    => $file->{ANSIPathName},
321            }
322        );
323
324        $self->image_sums->{$sum} = $image ;
325        $is_new_image = 1;
326    } else {
327        $image = $self->image_sums->{$sum};
328    }
329
330       
331    $self->sums->[$i] = $sum ;
332
333    $is_new_image;
334}
335
336
337sub _default_photo_name {
338    my ( $self, $file, $info, $i ) = @_;
339   
340   
341    my $name;
342    my $create_date = $info->{CreateDate};
343    my $ext;
344    my ( $vol, $path, $filename ) = File::Spec->splitpath($file);
345    ( $filename, $ext ) = split /\.\w+$/, $filename;
346   
347    my ( $yyyy, $mm, $dd, $hh, $mi, $ss ) = split /[:\s]/, $create_date ;
348 
349    my $chrono = join('', $yyyy, $mm, $dd);
350    if('Prefix' eq $self->default_photo_name){
351        $name = $self->default_name_prefix
352    }
353    elsif('File name' eq $self->default_photo_name){
354        $name = $filename
355    }
356    elsif('File path and name' eq $self->default_photo_name){
357        $name = sprintf(
358            "%s", 
359            File::Spec->catfile($path, $filename), 
360        )       
361    }   
362    elsif('Prefix + rank number' eq $self->default_photo_name){
363        $name = sprintf(
364            "%s%s", 
365            $self->default_name_prefix, 
366            1+$i,
367        )       
368    }   
369    elsif('Rank number + prefix' eq $self->default_photo_name){
370        $name = sprintf(
371            "%s%s", 
372            1+$i,
373            $self->default_name_prefix, 
374        )       
375    }   
376    elsif('Prefix + create date chrono' eq $self->default_photo_name){
377        $name = sprintf(
378            "%s%s", 
379            $self->default_name_prefix, 
380            $chrono,
381        )       
382    }   
383    elsif('Create date chrono + prefix' eq $self->default_photo_name){
384        $name = sprintf(
385            "%s%s", 
386            $chrono,
387            $self->default_name_prefix, 
388        )       
389    }   
390
391    $name;     
392}
393
394
395sub _create_gui_thumbnail {
396    my ( $self ) = @_;
397
398     eval {
399        printf("create gui thumbnail\n");
400        # use the preview image to create a gui display thumbnail
401        if(!$self->CreateGUIThumbnail())
402        {
403            print "CreateGUIThumbnail failed, use callback\n";
404            $self->ResizeCallback->(
405                $self->current_image->file,
406                $self->current_image->wx_thumb_file,
407                $self->type,
408                $self->wx_thumb_size,
409                $self->wx_thumb_size,
410                $self->wx_quality,
411            );
412               
413        }
414     };
415}
416
417sub RemoveImageSelection {
418    my ( $self ) = @_;
419   
420    return if (! scalar @{$self->sums} );
421    return if (! defined $self->image_selection );
422   
423    $self->_remove_image_list($self->image_selection);
424    # clear image selection
425    $self->image_selection([]);
426}
427
428sub _remove_image_list {
429    my ( $self, $list ) = @_;
430
431    # higher first, to keep same indexes during remove
432    my @images = reverse @$list;     
433    map {
434        $self->DeleteImage($_);
435        splice @{$self->sums}, $_, 1 ;
436        $self->wx_thumb_imglist->Remove($_);
437        shift @images;
438    }
439    @images;
440}
441
442sub RemoveImage {
443    my ( $self, $index ) = @_;
444
445    return if (! defined $self->image_selection );
446    return if (! defined $index );
447       
448    $self->DeleteImage($index);
449    splice @{$self->sums}, $index, 1 ;
450    $self->wx_thumb_imglist->Remove($index);
451       
452}
453
454# used for display in GUI. has to fit a square box ( wxImageList )
455sub CreateGUIThumbnail {
456    my ( $self ) = @_;
457
458#    return 1 if( -e $self->current_image->wx_thumb_file );
459    my $rval = 0;
460    print "CreateGUIThumbnail ", $self->current_image->wx_thumb_file, "\n";
461    my $image = new Image::Magick;
462
463    my $size = $self->wx_thumb_size||100;
464
465    my $status = $image->Set(size=>sprintf("%sx%s", 2*$size, 2*$size));
466    warn "$status" if $status ;
467
468    $status = $image->ReadImage(
469        $self->current_image->file
470    );
471    warn "$status" if $status;
472    return $rval if $status;
473
474    $self->current_image->width(
475        $image->Get('width')
476    );
477    $self->current_image->height(
478        $image->Get('height')
479    );
480
481    printf("%sx%s%s\n", $size, $size, '^');
482
483        # maximize size and keep aspect ratio
484    $status = $image->Thumbnail(
485        geometry=>sprintf("%s%s>", $size*$size, '@')
486    );
487    # to get adjusted to a square box
488    #$status = $image->Thumbnail(
489    #    geometry=>sprintf("%sx%s%s", $size, $size, '^')
490    #);
491    warn "$status" if $status;
492    return $rval if $status;
493
494#    causes strange behaviour with i18n -> yellow borders when local is other than EN
495#    $status = $image->Set(background=>"white");
496#    warn "$status" if $status ;
497
498    $status = $image->Set(Gravity=>"Center");
499    warn "$status" if $status ;
500
501    $image->Extent(
502        geometry=>sprintf("%sx%s", $size, $size),
503        gravity=>'center',
504    );
505
506    $image->Set(
507        quality=>$self->wx_quality||90
508    );
509
510    $status = $image->Strip();
511    warn "$status" if $status ;
512
513    # exif from original image
514    my $orientation = $self->current_image->exif_metadata->{Orientation};
515   
516    # Valid for Rotate 180, Rotate 90 CW, Rotate 270 CW
517    if( $orientation =~ m/Rotate (\d+)/ ){
518        printf(
519            "Rotate %s\n",
520            $1
521        );
522   
523        $image->Rotate( degrees=>$1 ) if $self->auto_rotate;   
524    }
525   
526
527    $image->Write(
528        sprintf(
529            "%s:%s",
530            $self->type,
531            $self->current_image->wx_thumb_file,
532        )
533    );
534
535    undef $image;
536   
537    $rval = 1;
538   
539    return $rval;
540}
541
542
543
544
545sub CreateResized {
546    my ( $self ) = @_;
547   
548    my $rval = 1 ;
549    return $rval if( -e $self->current_image->site_resized_file );
550
551    printf(
552        "Create resized %s\n",
553        $self->current_image->file,
554    );     
555
556    my $image = new Image::Magick;
557
558    my $status = $image->ReadImage(
559        $self->current_image->file
560    );
561    warn "$status" if $status ;
562    return 0 if $status;
563
564    my $w = $image->Get('width');
565    my $h = $image->Get('height');
566       
567    # should calculate the aspect ratio
568    my $resize_w = $self->resize_w;
569    my $resize_h = $self->resize_h;
570       
571    if( $w < $h ){
572        my $resize_w_ = $resize_w;
573        $resize_w = $resize_h;
574        $resize_h = $resize_w_;
575    }
576    printf("resize with blur value %s\n", $self->blur);
577    $status = $image->Resize(
578        geometry => sprintf("%sx%s>", $resize_w, $resize_h), 
579        filter => sprintf("%s", $self->filter), 
580        blur => $self->blur
581    );
582    warn "$status" if $status ;
583    return 0 if $status;
584
585    $status = $image->Set(Gravity=>"Center");
586    warn "$status" if $status ;
587
588    # exif from original image
589    my $orientation = $self->current_image->exif_metadata->{Orientation};
590   
591    # Valid for Rotate 180, Rotate 90 CW, Rotate 270 CW
592    if( $orientation =~ m/Rotate (\d+)/ ){
593        printf(
594            "Rotate %s\n",
595            $1
596        );
597   
598        $image->Rotate( degrees=>$1 ); 
599    }
600
601    printf("resize with quality value %s\n", $self->quality);
602    $status = $image->Set(quality=>$self->quality);
603    warn "$status" if $status ;
604
605    $status = $image->Set(interlace=>$self->interlace);
606    warn "$status" if $status ;
607
608    $image->Write(
609        sprintf(
610            "%s:%s",
611            $self->type,
612            $self->current_image->site_resized_file,
613        )
614    );
615    warn "$status" if $status ;
616    return 0 if $status;
617   
618    undef $image;
619
620   
621    $rval = 0 if $status;
622
623    return $rval;
624}
625
626sub CreateThumbnail {
627    my ( $self ) = @_;
628   
629    return 1 if( -e $self->current_image->site_thumb_file );
630   
631    my $rval = 1;
632
633    my $image = new Image::Magick;
634
635    my $status = $image->ReadImage(
636        $self->current_image->site_resized_file
637    );
638    warn "$status" if $status ;
639
640   
641    $status = $image->Resize(
642        geometry => sprintf(
643                                "%sx%s>", 
644                                $self->thumb_size, 
645                                $self->thumb_size
646                           ),
647    );
648    warn "$status" if $status ;
649
650    $status = $image->Set(Gravity=>"Center");
651    warn "$status" if $status ;
652
653    $status = $image->Set(quality=>$self->th_quality);
654    warn "$status" if $status ;
655
656    $status = $image->Strip();
657    warn "$status" if $status ;
658
659
660    $image->Write(
661        sprintf(
662            "%s:%s",
663            $self->type,
664            $self->current_image->site_thumb_file,
665        )
666    );
667   
668    undef $image;
669
670
671    $rval = 0 if $status;
672
673    return $rval;
674}
675
676
677
678sub _select_exif_data {
679    my ( $self, $exif ) = @_;
680
681    return {
682        map {
683            $_ => $exif->{$_},
684        }
685        qw/
686            CreateDate
687            ImageWidth
688            ImageHeight
689            Orientation
690            DateTimeOriginal
691            ISO
692            ExposureTime
693            ApertureValue
694            FocalLength
695            Lens
696            Exposure
697            Make
698            Model
699        /
700    };   
701}
702
703sub Store {
704    my ( $self ) = @_;
705   
706    my $data = $self->get_storable(
707        [ 
708            qw/
709                images
710                thumb_size
711                preview_ratio
712                type
713                filter
714                blur
715                quality
716                wx_quality
717                th_quality
718                prefix
719                author
720                count
721                resize_w
722                resize_h
723                new_files
724                storable_file
725                wx_thumb_size
726                current_image
727                exif_metadata
728                wx_thumb_dir
729                site_resized_dir
730                site_thumb_dir
731                userdata_dir
732                progress_msg
733                default_photo_name
734                default_name_prefix
735                upload_high
736                remove_uploaded_from_selection
737                auto_rotate
738                interlace
739                create_resized
740                use_exif_preview
741                image_sums
742                sums
743                version
744                imagelist_version
745                watermark_activate
746                watermark_activate_pwg_high
747                watermark_text
748                watermark_text_size
749                watermark_position
750                watermark_y
751                watermark_x
752                watermark_color
753            /
754        ] 
755   
756    );
757    eval {
758        store $data, $self->storable_file;
759    };
760    if($@){
761        print $@, "\n"; 
762    }
763}
764
765
766
767sub UploadSelection {
768    my ( $self ) = @_; 
769
770    my $viewer_callback = $self->UploadImagesViewerCallback ;
771
772    $self->image_selection([]) if !defined $self->image_selection;
773    $self->upload_rejects(
774        []
775    );
776
777    $self->count(
778        1
779    );
780
781    $self->upload_uploaded_count(0);
782    $self->upload_rejected_count(0);
783    $self->upload_begin_time(time);
784    $self->upload_selection_count(scalar @{$self->image_selection});
785    foreach(@{$self->image_selection}) {
786        # current image object         
787        $self->current_image(
788            $self->GetImage($_)
789        );
790        # prepare resized, high, thumbnail
791        $self->_upload_selection_prepare();
792
793        # transfert resized, high, thumbnail to site
794        my $status = $self->_upload_selection_transfert();
795        # log operations
796        $self->_upload_selection_log($status);
797        $self->count(
798            1+$self->count
799        );
800    }
801
802    if($self->remove_uploaded_from_selection){
803        $self->_remove_image_list($self->uploaded_images);
804        $viewer_callback->();
805    }
806
807    $self->_upload_selection_final_log();
808}
809
810sub _upload_selection_prepare {
811    my ( $self ) = @_;
812
813    $self->progress_thumbnail_refresh->();
814    # PREPARE
815    $self->_set_site_resized_file();
816    $self->_set_upload_msg(gettext("Preparing resized image for"));
817    $self->_upload_progress();
818
819    if( $self->create_resized ){
820        $self->_create_site_resized_file();
821        $self->_set_upload_msg(gettext("Resized image done for"));
822        $self->_upload_progress();
823    }
824    # the original is at the right size, no need to create a resize
825    else {
826        $self->current_image->site_resized_file(
827            $self->current_image->file,
828        );
829    }
830
831    # if upload high, rotate a copy of original file
832    if($self->upload_high){
833        $self->CreateHigh();
834        $self->_set_upload_msg(gettext("HD image done for"));
835        $self->_upload_progress();
836    }
837
838    eval {
839        $self->CreateThumbnail();
840    };
841    $self->_set_upload_msg(gettext("Thumbnail image done for"));
842    $self->_upload_progress();
843
844    # photo metadata
845    $self->_prepare_upload_properties();       
846
847}
848
849sub _upload_progress {
850    my ( $self, $value ) = @_;
851
852    eval {
853        $self->progress_msg_refresh->(
854            $self->upload_msg
855        );
856        # set current image thumbnail
857        # update upload progress dialog
858        #$self->progressbar_refresh->($value);
859    };
860    # user cancelled : dialog box is destroyed
861    croak gettext("Upload cancelled"), " .", $@ if $@ ;
862
863
864}
865
866sub _set_upload_msg {
867    my ( $self, $msg, $errmsg ) = @_;
868
869    $self->upload_msg(
870        sprintf(
871            "%s : %s - %s\n\n%s %s %s %s\n%s",
872            $msg,
873            $self->upload_file,
874            $self->upload_name,
875            gettext("Photo"),
876            $self->count,
877            gettext("on"),
878            $self->upload_selection_count,
879            $errmsg
880        )
881    );
882}
883
884sub _upload_selection_transfert {
885    my ( $self ) = @_;
886
887    $self->_set_upload_msg(gettext("Uploading"));
888    $self->_upload_progress(0);
889
890    # UPLOAD
891    my ( $status, $status_msg, $content ) = $self->pwg->UploadImage(
892        { 
893            yield=>$self->YieldCallback, 
894            bar=>$self->progressbar_refresh, 
895            msg=>$self->progress_msg_refresh,
896            msg_details=>$self->progress_msg_details_refresh,
897            resized_msg=>gettext("Uploading resized"),
898            thumbnail_msg=>gettext("Uploading thumbnail"),
899            highdef_msg=>gettext("Uploading high definition"),
900            checksum_msg=>gettext("Checksum for"),
901        } 
902    );
903    my $ok = 0;
904    # HTTP REQUEST OK
905    if ( $status ){
906        # PIWIGO RESULT ( HTTP may be ok while Piwigo is not )
907        $ok = 'fail' eq $content->{stat} ? 0 : 1;
908    }
909    else{
910        Wx::LogMessage(
911            "%s %s : %s",
912            gettext("Communication error with"),
913            $self->pwg->site_url,
914            $status_msg,
915        );
916    }
917    $self->upload_last_error(
918        $status_msg
919    );
920
921    $self->upload_error_content(
922        $content
923    );
924
925    $ok;
926}
927
928sub _upload_selection_log {
929    my ( $self, $ok ) = @_;
930
931    if($ok){
932        $self->_set_upload_msg(gettext("Uploaded"));
933        $self->_upload_progress(0);
934        push @{$self->uploaded_images}, $_;
935        $self->upload_uploaded_count(
936            1+$self->upload_uploaded_count       
937        );
938    } else {
939        $self->_set_upload_msg(gettext("An error has occured"), Dumper($self->upload_error_content));
940        $self->upload_rejected_count(
941            1+$self->upload_rejected_count
942        );
943    }   
944       
945}
946
947sub _upload_selection_final_log {
948    my ( $self ) = @_;
949
950    $self->upload_end_time(time);
951    $self->upload_duration(
952        $self->upload_end_time - $self->upload_begin_time
953    );
954
955    $self->progress_endinfo_refresh->(
956        sprintf(
957            "%s : %s\n\n%s : %s\n\n%s : %s\n\n\n%s : %s %s",
958            gettext("images processed"),
959            $self->count - 1,
960            gettext("images uploaded"),
961            $self->upload_uploaded_count,
962            gettext("images in errors and not uploaded"),
963            $self->upload_rejected_count,
964            gettext("Duration"),
965            $self->upload_duration,
966            gettext("seconds"),
967        )
968    );
969}
970
971sub _set_site_resized_file {
972    my ( $self ) = @_;
973
974    my ( $vol, $dir, $file ) = File::Spec->splitpath(
975        $self->current_image->file
976    );
977
978    $self->upload_file(
979        $file
980    );
981       
982    $self->upload_name(
983        $self->current_image->site_name
984    );
985    my $filename = $self->current_image->file_sum ;
986
987    # lately defined to make sure we have the last global properties ( resize_w, resize_h )
988    $self->current_image->site_resized_file( 
989        File::Spec->catfile(
990            $self->site_resized_dir,
991            sprintf(
992                "%s_%sx%s.%s",
993                $filename,
994                $self->resize_w,
995                $self->resize_h,
996                $self->type,
997            )
998        )
999    );
1000}
1001
1002sub _create_site_resized_file {
1003    my ( $self ) = @_;
1004
1005    eval {
1006        if(!$self->CreateResized()){
1007            $self->__create_resized_fallback();
1008        };
1009
1010        $self->_set_exif_tag(
1011            $self->current_image->site_resized_file,
1012            'Orientation',
1013            'Horizontal (normal)',
1014        ) if $self->auto_rotate;
1015
1016        $self->CreateWatermark(
1017            $self->watermark_text,
1018            $self->watermark_text_size,
1019            $self->watermark_position,
1020            $self->watermark_x,
1021            $self->watermark_y,
1022            $self->watermark_color,
1023            $self->current_image->site_resized_file
1024        ) if $self->watermark_activate;
1025    }
1026}
1027
1028sub _create_resized_fallback {
1029    my ( $self ) = @_;
1030    # use wx builtin rescale if IM fails
1031    printf("CreateResized failed %s. Use ResizeCallback\n", $@);
1032    # use method provided by the caller
1033    # source, target, type, ratio, width, $height
1034    $self->ResizeCallback->(
1035        $self->current_image->file,
1036        $self->current_image->site_resized_file,
1037        $self->type,
1038        undef,
1039        $self->resize_w,
1040        $self->resize_h,
1041        $self->quality,
1042    );
1043               
1044    $self->RotateImage(
1045        $self->current_image->site_resized_file,
1046    ) if $self->auto_rotate;
1047}
1048
1049# if we need to rotate
1050sub CreateHigh {
1051    my ( $self ) = @_;
1052
1053    my $bModifyOriginal;
1054    my $bRotate;
1055    my $bAddWatermark;
1056    my $orientation = $self->current_image->exif_metadata->{Orientation};
1057   
1058    # Valid for Rotate 180, Rotate 90 CW, Rotate 270 CW
1059    if( $self->auto_rotate and $orientation =~ m/Rotate (\d+)/ ){
1060        $bModifyOriginal = 1;
1061        $bRotate = 1;
1062    }
1063
1064    if( $self->watermark_activate_pwg_high ){
1065        $bModifyOriginal = 1;
1066        $bAddWatermark = 1;
1067    }
1068
1069    if($bModifyOriginal){
1070        $self-> _set_site_high_file ();
1071
1072        my $image = Image::Magick->new();
1073        # we read original
1074        my $status = $image->Read(
1075            $self->current_image->file
1076        );
1077        warn "$status ", $self->current_image->file, "\n" if $status ;
1078        return 0 if $status;
1079
1080        if($bRotate){
1081            $image->Rotate( degrees=>$1 );     
1082        }       
1083        $image->Write(
1084            $self->current_image->site_high_file
1085        );
1086        warn "$status ", $self->current_image->site_high_file, "\n" if $status ;
1087        return 0 if $status;
1088       
1089        undef $image;
1090
1091        if($bAddWatermark){
1092          my $file_out = $self->current_image->site_high_file;
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                $file_out
1101            );
1102        }
1103
1104
1105        $self->_set_exif_tag(
1106            $self->current_image->site_high_file,
1107            'Orientation',
1108            'Horizontal (normal)',
1109        );
1110
1111        # Now all images that need to be rotated are done. Update exif
1112        $self->current_image->exif_metadata->{Orientation} = 'Horizontal (normal)';
1113
1114
1115    }
1116    else{
1117        # high file is the original file
1118        $self->current_image->site_high_file(
1119            $self->current_image->file
1120        );
1121    }
1122
1123    return 1;
1124}
1125
1126# file name for original copy
1127sub _set_site_high_file {
1128        my ( $self ) = @_;
1129
1130        my ( $vol, $dir, $file ) = File::Spec->splitpath(
1131            $self->current_image->file
1132        );
1133   
1134        my ( $filename, $ext ) = split /\./, $file ;
1135   
1136        # high_file is a copy of original
1137        $self->current_image->site_high_file( 
1138            File::Spec->catfile(
1139                $self->site_resized_dir,
1140                sprintf(
1141                    "%s_high.%s",
1142                    $filename,
1143                    $self->type,
1144                )
1145            )
1146        );
1147}
1148
1149sub CreateWatermark {
1150    my ( $self, $text, $text_size, $position, $x, $y, $color, $file_out ) = @_;
1151   
1152    my $rval = 1 ;
1153    my $gravity = $self->gravity->{$position};
1154    my $fill = $self->rgbcolor->{$color};
1155
1156    # debug
1157    printf("Create watermark %s\n", $file_out);
1158
1159   
1160
1161    my $image = new Image::Magick;
1162   
1163    my $status = $image->ReadImage(
1164        $file_out
1165    );     
1166
1167    my $ratio = $image->Get('height')/($self->resize_h||$image->Get('height'));
1168    $ratio||=1;
1169    $text ||="Your watermark";
1170    $image->Annotate(
1171        pointsize => $text_size*$ratio,
1172        fill => $fill,
1173        x => $x*$ratio,
1174        y => $y*$ratio,
1175        text => $text,
1176        gravity => $gravity,
1177    );
1178                     
1179    $image->Write(
1180        sprintf(
1181            "%s:%s",
1182            $self->type,
1183            $file_out,
1184        )
1185    );
1186}
1187
1188sub _prepare_upload_properties {
1189    my ( $self ) = @_;
1190   
1191    $self->pwg->upload_high(
1192        $self->upload_high
1193    );
1194
1195    $self->pwg->site_high_file(
1196        $self->current_image->site_high_file
1197    );
1198
1199    $self->pwg->site_resized_file(
1200        $self->current_image->site_resized_file
1201    );
1202
1203    $self->pwg->site_thumb_file(
1204        $self->current_image->site_thumb_file
1205    );
1206
1207    $self->pwg->site_author(
1208        $self->current_image->site_author
1209    );
1210
1211    $self->pwg->site_comment(
1212        $self->current_image->site_comment
1213    );
1214
1215    $self->pwg->site_image_name(
1216        $self->current_image->site_name
1217    );
1218
1219    $self->pwg->site_img_date_creation(
1220        substr($self->current_image->create_date, 0, 10)
1221    );
1222
1223    $self->current_image->site_categories(
1224        $self->categories
1225    );
1226
1227    $self->pwg->categories(
1228        sprintf(
1229            "%s",
1230            join(';', @{$self->categories})
1231        )
1232    );
1233
1234    $self->pwg->site_tags(
1235        join(',', @{$self->current_image->site_tags})
1236    );
1237       
1238}
1239
1240# read Orientation exif tag from original image
1241# apply rotation to $file image
1242sub RotateImage {
1243    my ( $self, $file ) = @_;
1244   
1245    # exif from original image
1246    my $orientation = $self->current_image->exif_metadata->{Orientation};
1247
1248    # Valid for Rotate 180, Rotate 90 CW, Rotate 270 CW
1249    if( $orientation =~ m/Rotate (\d+)/ ){
1250        printf(
1251            "Rotate %s\n",
1252            $1
1253        );
1254
1255        my $image = Image::Magick->new();
1256       
1257        # read resized file
1258        my $status = $image->Read(
1259            $file
1260        );
1261        warn "$status ", $file, "\n" if $status ;
1262        return 0 if $status;
1263   
1264        $image->Rotate( degrees=>$1 ); 
1265       
1266        # write resized file
1267        $image->Write(
1268            $file
1269        );
1270        warn "$status ", $file, "\n" if $status ;
1271        return 0 if $status;
1272       
1273        undef $image;
1274   
1275    }   
1276    return 1;
1277}
1278
1279sub GetImage {
1280    my ( $self, $indx ) = @_;
1281   
1282    my $sum = $self->sums->[$indx];
1283
1284    $self->image_sums->{$sum};
1285}
1286
1287sub DeleteImage {
1288    my ( $self, $indx ) = @_;
1289   
1290    my $sum = $self->sums->[$indx];
1291
1292    delete $self->image_sums->{$sum};
1293}
1294
1295
12961;
Note: See TracBrowser for help on using the repository browser.