summaryrefslogtreecommitdiff
path: root/lib/Multi/Image.pm
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Multi/Image.pm')
-rw-r--r--lib/Multi/Image.pm205
1 files changed, 157 insertions, 48 deletions
diff --git a/lib/Multi/Image.pm b/lib/Multi/Image.pm
index b615ef4e..14ffc94b 100644
--- a/lib/Multi/Image.pm
+++ b/lib/Multi/Image.pm
@@ -10,16 +10,21 @@ use warnings;
use POE;
use Image::Magick;
use Image::MetaData::JPEG;
+use Time::HiRes 'time';
sub spawn {
my $p = shift;
POE::Session->create(
package_states => [
- $p => [qw| _start cmd_coverimage format compress update finish |],
+ $p => [qw| _start
+ cmd_coverimage cv_process cv_update cv_finish
+ cmd_screenshot scr_process scr_clean scr_finish
+ |],
],
heap => {
- imgpath => '/www/vndb/static/cv'
+ cvsize => [ 256, 400 ],
+ scrsize => [ 136, 102 ],
},
);
}
@@ -29,9 +34,10 @@ sub _start {
$_[KERNEL]->alias_set('image');
$_[KERNEL]->sig(shutdown => 'shutdown');
$_[KERNEL]->call(core => register => qr/^coverimage(?: ([0-9]+)|)$/, 'cmd_coverimage');
+ $_[KERNEL]->call(core => register => qr/^screenshot ([0-9]+|all|clean)$/, 'cmd_screenshot');
- # check for unprocessed cover images every day on 0:00 and 12:00 local time
- $_[KERNEL]->post(core => addcron => '0 0,12 * * *', 'coverimage');
+ # daily check for unprocessed cover images
+ $_[KERNEL]->post(core => addcron => '0 0 * * *', 'coverimage');
}
@@ -46,80 +52,183 @@ sub cmd_coverimage {
$_[HEAP]{todo} = [ map { -1*$_->[0]} @{$q->fetchall_arrayref([])} ];
if(!@{$_[HEAP]{todo}}) {
$_[KERNEL]->call(core => log => 2, 'No images to process');
- $_[KERNEL]->yield('finish');
+ $_[KERNEL]->yield('cv_finish');
return;
}
}
- $_[KERNEL]->yield(format => $_[HEAP]{todo}[0]);
+ $_[KERNEL]->yield(cv_process => $_[HEAP]{todo}[0]);
}
-sub format { # imgid
- $_[HEAP]{imgid} = $_[ARG0];
- $_[HEAP]{img} = sprintf '%s/%02d/%d.jpg', $_[HEAP]{imgpath}, $_[ARG0]%100, $_[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;
+sub cv_process { # id
+ my $start = time;
+
+ my $img = sprintf '%s/%02d/%d.jpg', $VNDB::VNDBopts{imgpath}, $_[ARG0]%100, $_[ARG0];
+
+ my $os = -s $img;
+ my $im = Image::Magick->new;
+ $im->Read($img);
+ $im->Set(magick => 'JPEG');
+ my($w, $h) = ($im->Get('width'), $im->Get('height'));
+ my($ow, $oh) = ($w, $h);
+ if($w > $_[HEAP]{cvsize}[0] || $h > $_[HEAP]{cvsize}[1]) {
+ if($w/$h > $_[HEAP]{cvsize}[0]/$_[HEAP]{cvsize}[1]) { # width is the limiting factor
+ $h *= $_[HEAP]{cvsize}[0]/$w;
+ $w = $_[HEAP]{cvsize}[0];
} else {
- $w *= 400/$h;
- $h = 400;
+ $w *= $_[HEAP]{cvsize}[1]/$h;
+ $h = $_[HEAP]{cvsize}[1];
}
- $_[HEAP]{im}->Thumbnail(width => $w, height => $h);
+ $im->Thumbnail(width => $w, height => $h);
}
+ $im->Set(quality => 80);
+ $im->Write($img);
+ undef $im;
- $_[KERNEL]->yield('compress');
+ my $md = Image::MetaData::JPEG->new($img);
+ $md->drop_segments('METADATA');
+ $md->save($img);
+
+ $_[KERNEL]->call(core => log => 2, 'Processed cover image %d in %.2fs: %.2fkB (%dx%d) -> %.2fkB (%dx%d)',
+ $_[ARG0], time-$start, $os/1024, $ow, $oh, (-s $img)/1024, $w, $h);
+ $_[KERNEL]->yield(cv_update => $_[ARG0]);
}
-sub compress {
- $_[HEAP]{im}->Set(quality => 80);
- $_[HEAP]{im}->Write($_[HEAP]{img});
- undef $_[HEAP]{im};
+sub cv_update { # id
+ if($Multi::SQL->do('UPDATE vn_rev SET image = ? WHERE image = ?', undef, $_[ARG0], -1*$_[ARG0])) {
+ $_[KERNEL]->yield(cv_finish => $_[ARG0]);
+ } elsif(!$_[ARG0]) {
+ $_[KERNEL]->delay(cv_update => 5 => $_[ARG0]);
+ } else {
+ $_[KERNEL]->call(core => log => 1, 'Image %d not present in the database!', $_[ARG0]);
+ $_[KERNEL]->yield(cv_finish => $_[ARG0]);
+ }
+}
+
- $_[HEAP]{md} = Image::MetaData::JPEG->new($_[HEAP]{img});
- $_[HEAP]{md}->drop_segments('METADATA');
- $_[HEAP]{md}->save($_[HEAP]{img});
- undef $_[HEAP]{md};
+sub cv_finish { # [id]
+ if($_[ARG0]) {
+ $_[HEAP]{todo} = [ grep $_[ARG0]!=$_, @{$_[HEAP]{todo}} ];
+ return $_[KERNEL]->yield(cv_process => $_[HEAP]{todo}[0])
+ if @{$_[HEAP]{todo}};
+ }
- $_[KERNEL]->call(core => log => 3, 'Compressed image %d to %.2fkB', $_[HEAP]{imgid}, (-s $_[HEAP]{img})/1024);
- $_[KERNEL]->yield('update');
+ $_[KERNEL]->post(core => finish => $_[HEAP]{curcmd});
+ delete @{$_[HEAP]}{qw| curcmd todo |};
}
-sub update {
- if($Multi::SQL->do('UPDATE vn_rev SET image = ? WHERE image = ?', undef, $_[HEAP]{imgid}, -1*$_[HEAP]{imgid})) {
- $_[KERNEL]->yield('finish');
- } elsif(!$_[ARG0]) {
- $_[KERNEL]->delay(update => 3, 3);
+
+
+sub cmd_screenshot {
+ my($cmd, $id) = @_[ARG0, ARG1];
+ $_[HEAP]{curcmd} = $_[ARG0];
+ $_[HEAP]{id} = $_[ARG1];
+
+ if($id eq 'clean') {
+ return $_[KERNEL]->yield('scr_clean');
+ } elsif($id eq 'all') {
+ my $q = $Multi::SQL->prepare('SELECT DISTINCT scr FROM vn_screenshots');
+ $q->execute();
+ $_[HEAP]{todo} = [ map $_->[0], @{$q->fetchall_arrayref([])} ];
} else {
- $_[KERNEL]->call(core => log => 1, 'Image %d not present in the database!', $_[HEAP]{imgid});
- $_[KERNEL]->yield('finish');
+ $_[HEAP]{todo} = [ $_[ARG1] ];
}
+ $_[KERNEL]->yield(scr_process => $_[HEAP]{todo}[0]);
}
-sub finish {
- if($_[HEAP]{imgid}) {
- $_[HEAP]{todo} = [ grep { $_[HEAP]{imgid} != $_ } @{$_[HEAP]{todo}} ];
- if(@{$_[HEAP]{todo}}) {
- $_[KERNEL]->yield(format => $_[HEAP]{todo}[0]);
- return;
+sub scr_process { # id
+ my $start = time;
+
+ my $sf = sprintf '%s/%02d/%d.jpg', $VNDB::VNDBopts{sfpath}, $_[ARG0]%100, $_[ARG0];
+ my $st = sprintf '%s/%02d/%d.jpg', $VNDB::VNDBopts{stpath}, $_[ARG0]%100, $_[ARG0];
+
+ # convert/compress full-size image
+ my $os = -s $sf;
+ my $im = Image::Magick->new;
+ $im->Read($sf);
+ $im->Set(magick => 'JPEG');
+ $im->Set(quality => 80);
+ $im->Write($sf);
+
+ # create thumbnail
+ my($w, $h) = ($im->Get('width'), $im->Get('height'));
+ my($ow, $oh) = ($w, $h);
+ if($w/$h > $_[HEAP]{scrsize}[0]/$_[HEAP]{scrsize}[1]) { # width is the limiting factor
+ $h *= $_[HEAP]{scrsize}[0]/$w;
+ $w = $_[HEAP]{scrsize}[0];
+ } else {
+ $w *= $_[HEAP]{scrsize}[1]/$h;
+ $h = $_[HEAP]{scrsize}[1];
+ }
+ $im->Thumbnail(width => $w, height => $h);
+ $im->Set(quality => 90);
+ $im->Write($st);
+ undef $im;
+
+ # remove metadata in both files
+ my $md = Image::MetaData::JPEG->new($sf);
+ $md->drop_segments('METADATA');
+ $md->save($sf);
+ $md = Image::MetaData::JPEG->new($st);
+ $md->drop_segments('METADATA');
+ $md->save($st);
+ undef $md;
+
+ $_[KERNEL]->call(core => log => 2, 'Processed screenshot #%d in %.2fs: %.1fkB -> %.1fkB (%dx%d), thumb: %.1fkB (%dx%d)',
+ $_[ARG0], time-$start, $os/1024, (-s $sf)/1024, $ow, $oh, (-s $st)/1024, $w, $h);
+ $_[KERNEL]->yield(scr_finish => $_[ARG0]);
+}
+
+
+sub scr_clean {
+ # not very efficient...
+ my $q = $Multi::SQL->prepare('SELECT DISTINCT scr FROM vn_screenshots');
+ $q->execute();
+ my @exists = map $_->[0], @{$q->fetchall_arrayref([])};
+
+ # not very efficient either...
+ my @files = map /\/([0-9]+)\.jpg$/?$1:(), glob "$VNDB::VNDBopts{sfpath}/*/*.jpg";
+
+ my($files, $thumbs, $bytes) = (0,0,0);
+ for my $id (@files) {
+ if(!grep $_==$id, @exists) {
+ my $f = sprintf '%s/%02d/%d.jpg', $VNDB::VNDBopts{stpath}, $id%100, $id;
+ my $t = sprintf '%s/%02d/%d.jpg', $VNDB::VNDBopts{stpath}, $id%100, $id;
+ $bytes += -s $f;
+ $files++;
+ unlink $f;
+ if(-f $t) {
+ $bytes += -s $t;
+ $thumbs++;
+ unlink $t;
+ }
+ $_[KERNEL]->call(core => log => 3, 'Removing screenshot #%d', $id);
}
}
+ $_[KERNEL]->call(core => log => 2, 'Removed %d + %d unused files, total of %.2fMB freed.',
+ $files, $thumbs, $bytes/1024/1024) if $files;
+ $_[KERNEL]->call(core => log => 2, 'No unused screenshots found') if !$files;
+ $_[KERNEL]->yield('scr_finish');
+}
+
+
+sub scr_finish { # [id]
+ if($_[ARG0]) {
+ $_[HEAP]{todo} = [ grep $_!=$_[ARG0], @{$_[HEAP]{todo}} ];
+ return $_[KERNEL]->yield(scr_process => $_[HEAP]{todo}[0])
+ if @{$_[HEAP]{todo}};
+ }
+
$_[KERNEL]->post(core => finish => $_[HEAP]{curcmd});
- delete @{$_[HEAP]}{qw| curcmd imgid img im md todo |};
+ delete @{$_[HEAP]}{qw| curcmd todo |};
}
+
1;