source: extensions/pLoader/trunk/src/Uploader/ResizeWorker.pm @ 6709

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

Fix watermark creation issue + high resized ignored.

File size: 15.1 KB
Line 
1package Uploader::ResizeWorker;
2use threads;
3use threads::shared;
4use strict;
5use base qw/Uploader::Object/;
6use Image::Magick;
7use Data::Dumper;
8
9$|=1;
10
11__PACKAGE__->mk_accessors(qw/
12    preferences
13    wx_thumb_dir
14    thumb_dir
15    resized_dir
16    write_type
17    progress_event
18    done_event
19    event_handler
20    cancel_event
21    gravity
22    rgbcolor
23/);
24
25
26sub Init {
27    my ( $self ) =@_;
28
29    $self->gravity(
30        { 
31            'Top'          => 'North',
32            'Left'         => 'West',
33            'Right'        => 'East',
34            'Bottom'       => 'South',
35            'Top left'     => 'NorthWest',
36            'Top right'    => 'NorthEast',
37            'Bottom left'  => 'SouthWest',
38            'Bottom right' => 'SouthEast',
39            'Center'       => 'Center',
40       }   
41    );   
42
43    $self->rgbcolor(
44        {
45            "White" => '#FFFFFF',
46            "Black" => '#000000',
47        }   
48    );
49}
50
51
52sub cancel_image {
53    my ( $self, $image ) = @_;
54   
55    #must check if $image is a valid hash
56    return unless 'HASH' eq ref $image;
57    return unless $image->{image_id};
58
59    $self->log_image_progress(
60        $image,
61        $self->localized_msg->{"cancelled"},
62        0,
63    );
64}
65
66
67sub process_image {
68    my ( $self, $handler, $progress_event, $resize_done_event, $image ) = @_;
69
70    $self->event_handler(
71        $handler
72    );
73
74
75    $self->progress_event(
76        $progress_event
77    );
78
79    $self->done_event(
80        $resize_done_event
81    );
82
83    $self->resize_image($image);
84    $self->process_high_image($image);
85    $self->thumbnail_image($image);
86
87    $self->post_image_done_event($image);
88}
89
90
91sub post_image_progress_event {
92    my ( $self, $image ) = @_;
93
94    $self->post_image_event(
95        $self->progress_event,
96        $image
97    );
98}
99
100
101sub post_image_done_event {
102    my ( $self, $image ) = @_;
103
104    $image->{status}   = $self->localized_msg->{"prepared, waiting for transfer"};
105    $image->{progress} = 25;
106
107    $self->post_image_event(
108        $self->done_event,
109        $image
110    );
111}
112
113
114sub post_image_cancel_event {
115    my ( $self, $image ) = @_;
116
117    $image->{status}   = "cancelled";
118    $image->{progress} = 0;
119
120    $self->post_image_event(
121        $self->cancel_event,
122        $image
123    );
124}
125
126
127
128
129sub post_image_event {
130    my ( $self, $event_type, $image ) = @_;
131
132    my $thread_event = Wx::PlThreadEvent->new(
133        -1,
134        $event_type,
135        shared_clone($image)
136    );
137
138    eval {
139        Wx::PostEvent($self->event_handler, $thread_event);
140    }
141
142}
143
144
145sub resize_image {
146    my ( $self, $image ) = @_;
147
148    $self->log_image_progress(
149        $image,
150        $self->localized_msg->{"preparing web size"},
151        5,
152    );
153
154    my $preferences = $image->{preferences};
155
156    if( $preferences->{create_resized} ){
157        $self->create_resized($image);
158    }
159    # the original is at the right size, no need to create a resize
160    else {
161        #printf("original no resized %s\n", $self->create_resized);
162        $image->{site_resized_file} = $image->{file};
163    }
164
165    $self->log_image_progress(
166        $image,
167        $self->localized_msg->{"web size prepared"},
168        10,
169    );
170
171}
172
173
174sub log_image_progress {
175    my ( $self, $image, $status, $value ) = @_;
176
177    $image->{status}   = $status;
178    $image->{progress} = $value;
179    $self->post_image_progress_event($image);
180}
181
182
183sub process_high_image {
184    my ( $self, $image ) = @_;
185
186    my $decode = {
187        'No' => 0,
188        'Yes, use HD resized of the original photo' => 'HD',
189        'Yes, use a copy of the original photo' => 'ORIGINAL',
190    };
191
192    my $preferences = $image->{preferences};
193    $image->{upload_high} = $decode->{$preferences->{upload_hd}};
194    # if upload high, rotate a copy of original file
195    if($image->{upload_high}){
196        $self->create_high($image);
197    }
198}
199
200
201# $image is a hash, not an object
202sub create_resized {
203    my ( $self, $image ) = @_;
204
205    my $rval = 1 ;
206
207    $image->{site_resized_file} = File::Spec->catfile(
208        $self->resized_dir,
209        sprintf(
210            "%s.%s.%s",
211            $image->{image_id},
212            $image->{global_rank},
213            $self->write_type,
214        ),
215    );
216
217    my $imgk = new Image::Magick;
218
219    my $status = $imgk->ReadImage(
220        $image->{file}
221    );
222    warn "$status" if $status ;
223    return 0 if $status;
224
225    my $w = $imgk->Get('width');
226    my $h = $imgk->Get('height');
227
228    $status = $imgk->Set(Gravity=>"Center");
229    warn "$status" if $status ;
230
231    # exif from original image
232    my $orientation = $image->{exif_metadata}{Orientation};
233    my $preferences = $image->{preferences};
234   
235    # Valid for Rotate 180, Rotate 90 CW, Rotate 270 CW
236    if( $orientation =~ m/Rotate (\d+)/ ){
237        printf(
238            "Rotate %s\n",
239            $1
240        );
241   
242        $imgk->Rotate( degrees=>$1 ) if $preferences->{auto_rotate};   
243    }
244
245
246    #printf("resize with blur value %s\n", $self->blur);
247    $status = $imgk->Resize(
248        geometry => sprintf(
249            "%sx%s>",
250            $preferences->{resize_w},
251            $preferences->{resize_h}
252        ),
253        filter => sprintf(
254            "%s",
255            $preferences->{filter}
256        ), 
257        blur => $preferences->{blur}
258    );
259    warn "$status" if $status ;
260    return 0 if $status;
261
262    #printf("resize with quality value %s\n", $self->quality);
263    $status = $imgk->Set(quality=>$preferences->{quality});
264    warn "$status" if $status ;
265
266    $status = $imgk->Set(interlace=>$preferences->{interlace});
267    warn "$status" if $status ;
268
269    $imgk->Write(
270        sprintf(
271            "%s:%s",
272            $self->write_type,
273            $image->{site_resized_file},
274        )
275    );
276    warn "$status" if $status ;
277    return 0 if $status;
278   
279    undef $imgk;
280
281    if($preferences->{watermark_activate}){
282        $self->create_watermark(
283            $preferences,
284            $image->{site_resized_file}
285        );
286    }
287
288   
289    $rval = 0 if $status;
290
291    return $rval;
292}
293
294# $image is a hash, not an object
295sub thumbnail_image {
296    my ( $self, $image ) = @_;
297   
298    my $rval = 1;
299
300    $image->{site_thumb_file} = File::Spec->catfile(
301        $self->thumb_dir,
302        sprintf(
303            "%s.%s.%s",
304            $image->{image_id},
305            $image->{global_rank},
306            $self->write_type,
307        ),
308    );
309
310
311    my $imgk = new Image::Magick;
312
313    my $status = $imgk->ReadImage(
314        $image->{site_resized_file}
315    );
316    warn "$status" if $status ;
317
318    my $preferences = $image->{preferences};
319    my $pattern = $preferences->{thumbnail_shape_square} ?
320        "%sx%s^" :
321        "%sx%s>" ;
322    $status = $imgk->Resize(
323        geometry => sprintf(
324            $pattern, 
325            $preferences->{thumb_size}, 
326            $preferences->{thumb_size}
327        ),
328    );
329    warn "$status" if $status ;
330
331    $status = $imgk->Set(Gravity=>"Center");
332    warn "$status" if $status ;
333
334    $status = $imgk->Crop(
335        geometry=>sprintf(
336            "%sx%s+0+0",
337            $preferences->{thumb_size},
338            $preferences->{thumb_size}
339        )
340    ) if $preferences->{thumbnail_shape_square};
341
342
343    $status = $imgk->Set(quality=>$preferences->{th_quality});
344    warn "$status" if $status ;
345
346    $status = $imgk->Strip();
347    warn "$status" if $status ;
348
349
350    $imgk->Write(
351        sprintf(
352            "%s:%s",
353            $self->write_type,
354            $image->{site_thumb_file},
355        )
356    );
357   
358    undef $image;
359
360
361    $rval = 0 if $status;
362
363    return $rval;
364}
365
366
367sub create_high {
368    my ( $self, $image ) = @_;
369
370    $self->log_image_progress(
371        $image,
372        $self->localized_msg->{"preparing high"},
373        15,
374    );
375
376    $self->set_site_high_file($image);
377
378    my $bModifyOriginal;
379    my $bRotate;
380    my $bAddWatermark;
381    my $bResize;
382    my $orientation = $image->{exif_metadata}{Orientation};
383    my $degrees;
384   
385    my $preferences = $image->{preferences};
386    # Valid for Rotate 180, Rotate 90 CW, Rotate 270 CW
387    if( $preferences->{auto_rotate} and $orientation =~ m/Rotate (\d+)/ ){
388        $bModifyOriginal = 1;
389        $bRotate = 1;
390        $degrees = $1;
391    }
392
393    if( $preferences->{watermark_activate_pwg_high} ){
394        $bModifyOriginal = 1;
395        $bAddWatermark = 1;
396    }
397   
398    # HD resize
399    if('HD' eq $image->{upload_high}){
400        $bModifyOriginal = 1;
401        $bResize = 1;
402    }
403
404    if($bModifyOriginal){
405
406        my $imgk = Image::Magick->new();
407        # we read original
408        my $status = $imgk->Read(
409            $image->{file}
410        );
411        warn "$status ", $image->{file}, "\n" if $status ;
412        return 0 if $status;
413
414        if($bRotate){
415            $imgk->Rotate( degrees=>$degrees );   
416        }       
417        $imgk->Write(
418            $image->{site_high_file}
419        );
420        warn "$status ", $image->{site_high_file}, "\n" if $status ;
421        return 0 if $status;
422
423        if($bResize){
424            $status = $imgk->Resize(
425                geometry => sprintf(
426                    "%sx%s>",
427                    $preferences->{hd_w},
428                    $preferences->{hd_h}
429                ), 
430                filter => sprintf(
431                    "%s",
432                    $preferences->{hd_filter}
433                ), 
434                blur => $preferences->{hd_blur}
435            );
436            warn "$status" if $status ;
437            return 0 if $status;
438        }
439       
440        #printf("resize with quality value %s\n", $self->quality);
441        $status = $imgk->Set(quality=>$preferences->{quality});
442        warn "$status" if $status ;
443
444        $status = $imgk->Set(interlace=>$preferences->{interlace});
445        warn "$status" if $status ;
446       
447        $imgk->Write(
448            sprintf(
449                "%s:%s",
450                $self->write_type,
451                $image->{site_high_file},
452            )
453        );
454        warn "$status" if $status ;
455       
456        undef $imgk;
457
458        if($bAddWatermark){
459            $self->create_watermark(
460                $image->{preferences},
461                $image->{site_high_file}
462            );
463        }
464
465        $self->set_file_exif_tag(
466            $image->{site_high_file},
467            'Orientation',
468            'Horizontal (normal)',
469        );
470
471        # Now all images that need to be rotated are done. Update exif
472        $image->{exif_metadata}{Orientation} = 'Horizontal (normal)';
473
474
475    }
476    else{
477        # high file is the original file
478        $image->{site_high_file} = $image->{file};
479        #printf("site high file %s\n", $self->current_image->site_high_file);
480    }
481    $self->log_image_progress(
482        $image,
483        $self->localized_msg->{"high prepared"},
484        25,
485    );
486
487    return 1;
488
489}
490
491
492sub set_site_high_file {
493    my ( $self, $image ) = @_;
494
495    my ( $vol, $dir, $file ) = File::Spec->splitpath(
496        $image->{file}
497    );
498   
499    my ( $filename, $ext ) = split /\./, $file ;
500   
501    # high_file is a resized of original
502    $image->{site_high_file} = File::Spec->catfile(
503        $self->resized_dir,
504        sprintf(
505            "%s_high.%s.%s",
506            $image->{image_id},
507            $image->{global_rank},
508            $self->write_type,
509        ),
510    );
511}
512
513
514sub create_watermark {
515    my ( $self, $preferences, $file_out ) = @_;
516   
517    my $rval = 1 ;
518
519    my $text = $preferences->{watermark_text};
520    my $text_size = $preferences->{watermark_text_size};
521    my $w_position = $preferences->{watermark_position};
522    my $x = $preferences->{watermark_x};
523    my $y = $preferences->{watermark_y};
524    my $color = $preferences->{watermark_color};
525
526    my $gravity = $self->gravity->{$w_position};
527    my $fill = $self->rgbcolor->{$color};
528
529    # debug
530    #printf("Create watermark %s\n", $file_out);
531
532   
533
534    my $imgk = new Image::Magick;
535   
536    my $status = $imgk->ReadImage(
537        $file_out
538    );     
539
540    my $ratio = $imgk->Get('height')/($preferences->{resize_h}||$imgk->Get('height'));
541    $ratio||=1;
542    $text ||="Your watermark";
543    $imgk->Annotate(
544        pointsize => $text_size*$ratio,
545        fill => $fill,
546        x => $x*$ratio,
547        y => $y*$ratio,
548        text => $text,
549        gravity => $gravity,
550    );
551                     
552    $imgk->Write(
553        sprintf(
554            "%s:%s",
555            $self->write_type,
556            $file_out,
557        )
558    );
559}
560
561
562sub set_file_exif_tag {
563    my ( $self, $file, $tag, $newValue ) = @_;   
564
565    my $options = {};
566    # Create a new Image::ExifTool object
567    my $exifTool = new Image::ExifTool;
568
569    # Extract meta information from an image
570    $exifTool->ExtractInfo($file, $options);
571
572    # Set a new value for a tag
573    $exifTool->SetNewValue($tag, $newValue);
574
575    # Write new meta information to a file
576    $exifTool->WriteInfo($file);
577
578}
579
580
581# used for display in GUI. has to fit a square box ( wxImageList )
582# $image is an object
583sub create_wx_thumbnail {
584    my ( $self, $image ) = @_;
585
586
587    $image->wx_thumb_file( 
588        File::Spec->catfile(
589            $self->wx_thumb_dir,
590            sprintf(
591                "%s.%s.%s",
592                $image->image_id,
593                $image->global_rank,
594                $self->write_type,
595            ),
596        )
597    );
598
599
600    my $rval = 0;
601    my $imgk = new Image::Magick;
602
603    my $preferences = $image->{preferences};
604    my $size = $preferences->{wx_thumb_size}||100;
605
606    my $status = $imgk->Set(size=>sprintf("%sx%s", 2*$size, 2*$size));
607    warn "$status" if $status ;
608
609    $status = $imgk->ReadImage(
610        $image->file
611    );
612    warn "$status" if $status;
613    return $rval if $status;
614
615    # maximize size and keep aspect ratio
616    $status = $imgk->Thumbnail(
617        geometry=>sprintf("%s%s>", $size*$size, '@')
618    );
619    # to get adjusted to a square box
620    #$status = $image->Thumbnail(
621    #    geometry=>sprintf("%sx%s%s", $size, $size, '^')
622    #);
623    warn "$status" if $status;
624    return $rval if $status;
625
626    $status = $imgk->Set(Gravity=>"Center");
627    warn "$status" if $status ;
628
629    $imgk->Extent(
630        geometry=>sprintf("%sx%s", $size, $size),
631        gravity=>'center',
632    );
633   
634    $imgk->Set(
635        quality=>$preferences->{wx_quality}||90
636    );
637
638    $status = $imgk->Strip();
639    warn "$status" if $status ;
640
641    # exif from original image
642    my $orientation = $image->exif_metadata->{Orientation};
643   
644    # Valid for Rotate 180, Rotate 90 CW, Rotate 270 CW
645    if( $orientation =~ m/Rotate (\d+)/ ){
646        printf(
647            "Rotate %s\n",
648            $1
649        );
650   
651        $imgk->Rotate( degrees=>$1 ) if $preferences->{auto_rotate};   
652    }
653   
654
655    $imgk->Write(
656        sprintf(
657            "%s:%s",
658            $self->write_type,
659            $image->wx_thumb_file,
660        )
661    );
662
663    undef $imgk;
664   
665    $rval = 1;
666   
667    return $rval;
668}
669
670
6711;
Note: See TracBrowser for help on using the repository browser.