summaryrefslogtreecommitdiff
path: root/lib/Multi/Image.pm
blob: f9ccd83ed5aed2191b50e9ba6461726ae1c329fd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119

#
#  Multi::Image  -  Image compressing and resizing
#

package Multi::Image;

use strict;
use warnings;
use POE;
use Image::Magick;
use Image::MetaData::JPEG;


sub spawn {
  my $p = shift;
  POE::Session->create(
    package_states => [
      $p => [qw| _start cmd_coverimage format compress update finish |],
    ],
    heap => {
      imgpath => '/www/vndb/static/cv'
    },
  );
}


sub _start {
  $_[KERNEL]->alias_set('image');
  $_[KERNEL]->sig(shutdown => 'shutdown');
  $_[KERNEL]->call(core => register => qr/^coverimage(?: ([0-9]+)|)$/, 'cmd_coverimage');

 # check for unprocessed cover images every day on 0:00 and 12:00 local time
  $_[KERNEL]->post(core => addcron => '0 0,12 * * *', 'coverimage');
}


sub cmd_coverimage {
  $_[HEAP]{curcmd} = $_[ARG0];

  if($_[ARG1]) {
    $_[HEAP]{todo} = [ $_[ARG1] ];
  } else {
    my $q = $Multi::SQL->prepare('SELECT image FROM vn_rev WHERE image < 0');
    $q->execute();
    $_[HEAP]{todo} = [ map { -1*$_->[0]} @{$q->fetchall_arrayref([])} ];
    if(!@{$_[HEAP]{todo}}) {
      $_[KERNEL]->call(core => log => 2, 'No images to process');
      $_[KERNEL]->yield('finish');
      return;
    }
  }
  $_[KERNEL]->yield(format => $_[HEAP]{todo}[0]);
}


sub format { # imgid
  $_[HEAP]{imgid} = $_[ARG0];
  $_[HEAP]{img} = sprintf '%s/%02d/%d.jpg', $_[HEAP]{imgpath}, $_[ARG0]%50, $_[ARG0];
  $_[KERNEL]->call(core => log => 3, 'Processing image %d', $_[HEAP]{imgid});

  $_[HEAP]{im} = Image::Magick->new;
  $_[HEAP]{im}->Read($_[HEAP]{img});
  $_[HEAP]{im}->Set(magick => 'JPEG');
  my($w, $h) = ($_[HEAP]{im}->Get('width'), $_[HEAP]{im}->Get('height'));
  if($w > 256 || $h > 400) {
    $_[KERNEL]->call(core => log => 3, 'Image too large (%dx%d), resizing', $w, $h);
    if($w/$h > 256/400) { # width is the limiting factor
      $h *= 256/$w;
      $w = 256;
    } else {
      $w *= 400/$h;
      $h = 400;
    }
    $_[HEAP]{im}->Thumbnail(width => $w, height => $h);
  } 

  $_[KERNEL]->yield('compress');
}


sub compress {
  $_[HEAP]{im}->Set(quality => 80);
  $_[HEAP]{im}->Write($_[HEAP]{img});
  undef $_[HEAP]{im};

  $_[HEAP]{md} = Image::MetaData::JPEG->new($_[HEAP]{img});
  $_[HEAP]{md}->drop_segments('METADATA');
  $_[HEAP]{md}->save($_[HEAP]{img});
  undef $_[HEAP]{md};

  $_[KERNEL]->call(core => log => 3, 'Compressed image %d to %.2fkB', $_[HEAP]{imgid}, (-s $_[HEAP]{img})/1024);
  $_[KERNEL]->yield('update');
}


sub update {
  $Multi::SQL->do('UPDATE vn_rev SET image = ? WHERE image = ?', undef, $_[HEAP]{imgid}, -1*$_[HEAP]{imgid});

  $_[KERNEL]->yield('finish');
}


sub finish {
  if($_[HEAP]{imgid}) {
    $_[HEAP]{todo} = [ grep { $_[HEAP]{imgid} != $_ } @{$_[HEAP]{todo}} ];
    if(@{$_[HEAP]{todo}}) {
      $_[KERNEL]->yield(format => $_[HEAP]{todo}[0]);
      return;
    }
  }

  $_[KERNEL]->post(core => finish => $_[HEAP]{curcmd});
  delete @{$_[HEAP]}{qw| curcmd imgid img im md todo |};
}


1;