summaryrefslogtreecommitdiff
path: root/lib/Multi
diff options
context:
space:
mode:
authorYorhel <git@yorhel.nl>2009-07-18 20:31:50 +0200
committerYorhel <git@yorhel.nl>2009-07-18 20:31:50 +0200
commitae53633780260b152a105c83fb4a7a72cd82d33b (patch)
tree4eafe357d9195c617e300ff1128ec87e336cf298 /lib/Multi
parent5cbaaa3616a002a708af785bfa7e0774d50e0751 (diff)
Rewrote Multi::Image
Decided to remove the Image::MetaData::JPEG dependency as well, as the Image::Magick::Thumbnail function removes a lot of unecessary information, profiles and other data as well.
Diffstat (limited to 'lib/Multi')
-rw-r--r--lib/Multi/Image.pm225
1 files changed, 61 insertions, 164 deletions
diff --git a/lib/Multi/Image.pm b/lib/Multi/Image.pm
index fe3d411e..c3a0d04f 100644
--- a/lib/Multi/Image.pm
+++ b/lib/Multi/Image.pm
@@ -9,7 +9,6 @@ use strict;
use warnings;
use POE;
use Image::Magick;
-use Image::MetaData::JPEG;
use Time::HiRes 'time';
@@ -18,8 +17,7 @@ sub spawn {
POE::Session->create(
package_states => [
$p => [qw| _start
- cmd_coverimage cv_process cv_update cv_finish
- cmd_screenshot scr_process scr_update scr_clean scr_finish
+ _start shutdown cv_check cv_process scr_check scr_process
|],
],
heap => {
@@ -28,6 +26,8 @@ sub spawn {
cvpath => $VNDB::ROOT.'/static/cv',
sfpath => $VNDB::ROOT.'/static/sf',
stpath => $VNDB::ROOT.'/static/st',
+ check_delay => 3600,
+ @_,
},
);
}
@@ -36,212 +36,109 @@ sub spawn {
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');
+ $_[KERNEL]->yield('cv_check');
+ $_[KERNEL]->yield('scr_check');
}
-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('cv_finish');
- return;
- }
- }
- $_[KERNEL]->yield(cv_process => $_[HEAP]{todo}[0]);
+sub shutdown {
+ $_[KERNEL]->delay('cv_check');
+ $_[KERNEL]->delay('scr_check');
}
-sub cv_process { # id
- my $start = time;
+sub cv_check {
+ $_[KERNEL]->delay('cv_check');
+ $_[KERNEL]->post(pg => query => 'SELECT image FROM vn_rev WHERE image < 0 LIMIT 1', undef, 'cv_process');
+}
+
- my $img = sprintf '%s/%02d/%d.jpg', $_[HEAP]{cvpath}, $_[ARG0]%100, $_[ARG0];
+sub cv_process { # num, res
+ return $_[KERNEL]->delay(cv_check => $_[HEAP]{check_delay}) if $_[ARG0] == 0;
+ my $id = -1*$_[ARG1][0]{image};
+ my $start = time;
+ my $img = sprintf '%s/%02d/%d.jpg', $_[HEAP]{cvpath}, $id%100, $id;
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 *= $_[HEAP]{cvsize}[1]/$h;
- $h = $_[HEAP]{cvsize}[1];
- }
- $im->Thumbnail(width => $w, height => $h);
- }
+ my($old, $new) = do_resize($im, $_[HEAP]{cvsize});
$im->Set(quality => 80);
$im->Write($img);
- undef $im;
- my $md = Image::MetaData::JPEG->new($img);
- $md->drop_segments('METADATA');
- $md->save($img);
+ $_[KERNEL]->post(pg => do => 'UPDATE vn_rev SET image = image*-1 WHERE image = ?', [ -1*$id ]);
+ $_[KERNEL]->call(core => log => 'Processed cover image %d in %.2fs: %.2fkB (%dx%d) -> %.2fkB (%dx%d)',
+ $id, time-$start, $os/1024, $$old[0], $$old[1], (-s $img)/1024, $$new[0], $$new[1]);
- $_[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]);
+ $_[KERNEL]->yield('cv_check');
}
-sub cv_update { # id
- if($Multi::SQL->do('UPDATE vn_rev SET image = ? WHERE image = ?', undef, $_[ARG0], -1*$_[ARG0]) > 0) {
- $_[KERNEL]->yield(cv_finish => $_[ARG0]);
- } else {
- $_[KERNEL]->call(core => log => 1, 'Image %d not present in the database!', $_[ARG0]);
- $_[KERNEL]->yield(cv_finish => $_[ARG0]);
- }
-}
-
-
-sub cv_finish { # [id]
- if($_[ARG0]) {
- $_[HEAP]{todo} = [ grep $_[ARG0]!=$_, @{$_[HEAP]{todo}} ];
- return $_[KERNEL]->yield(cv_process => $_[HEAP]{todo}[0])
- if @{$_[HEAP]{todo}};
- }
-
- $_[KERNEL]->post(core => finish => $_[HEAP]{curcmd});
- delete @{$_[HEAP]}{qw| curcmd todo |};
+sub scr_check {
+ $_[KERNEL]->delay('scr_check');
+ $_[KERNEL]->post(pg => query => 'SELECT id FROM screenshots WHERE status = 0 LIMIT 1', undef, 'scr_process');
}
+sub scr_process { # num, res
+ return $_[KERNEL]->delay(scr_check => $_[HEAP]{check_delay}) if $_[ARG0] == 0;
-
-sub cmd_screenshot {
- my($cmd, $id) = @_[ARG0, ARG1];
- $_[HEAP]{curcmd} = $_[ARG0];
- $_[HEAP]{id} = $_[ARG1];
-
- if(!$id) {
- my $q = $Multi::SQL->prepare('SELECT id FROM screenshots WHERE status = 0');
- $q->execute();
- $_[HEAP]{todo} = [ map { $_->[0]} @{$q->fetchall_arrayref([])} ];
- if(!@{$_[HEAP]{todo}}) {
- $_[KERNEL]->call(core => log => 2, 'No screenshots to process');
- $_[KERNEL]->yield('scr_finish');
- return;
- }
-
- } elsif($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 {
- $_[HEAP]{todo} = [ $_[ARG1] ];
- }
-
- $_[KERNEL]->yield(scr_process => $_[HEAP]{todo}[0]);
-}
-
-
-sub scr_process { # id
+ my $id = $_[ARG1][0]{id};
my $start = time;
-
- my $sf = sprintf '%s/%02d/%d.jpg', $_[HEAP]{sfpath}, $_[ARG0]%100, $_[ARG0];
- my $st = sprintf '%s/%02d/%d.jpg', $_[HEAP]{stpath}, $_[ARG0]%100, $_[ARG0];
-
- # convert/compress full-size image
+ my $sf = sprintf '%s/%02d/%d.jpg', $_[HEAP]{sfpath}, $id%100, $id;
+ my $st = sprintf '%s/%02d/%d.jpg', $_[HEAP]{stpath}, $id%100, $id;
my $os = -s $sf;
+
+ # convert/compress full-size image
my $im = Image::Magick->new;
$im->Read($sf);
$im->Set(magick => 'JPEG');
$im->Set(quality => 90);
$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);
+ # create thumbnail
+ my($old, $new) = do_resize($im, $_[HEAP]{scrsize});
$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_update => $_[ARG0], $ow, $oh);
-}
+ $_[KERNEL]->post(pg => do =>
+ 'UPDATE screenshots SET status = 1, width = ?, height = ? WHERE id = ?',
+ [ $$old[0], $$old[1], $id ]
+ );
+ $_[KERNEL]->call(core => log =>
+ 'Processed screenshot #%d in %.2fs: %.1fkB -> %.1fkB (%dx%d), thumb: %.1fkB (%dx%d)',
+ $_[ARG0], time-$start, $os/1024, (-s $sf)/1024, $$old[0], $$old[1], (-s $st)/1024, $$new[0], $$new[1]
+ );
-sub scr_update { # id, width, height
- if($Multi::SQL->do('UPDATE screenshots SET status = 1, width = ?, height = ? WHERE id = ?', undef, $_[ARG1], $_[ARG2], $_[ARG0]) > 0) {
- $_[KERNEL]->yield(scr_finish => $_[ARG0]);
- } else {
- $_[KERNEL]->call(core => log => 1, 'Screenshot %d not present in the database!', $_[ARG0]);
- $_[KERNEL]->yield(scr_finish => $_[ARG0]);
- }
+ $_[KERNEL]->yield('scr_check');
}
-sub scr_clean {
- my $sql = ' FROM screenshots s WHERE NOT EXISTS(SELECT 1 FROM vn_screenshots vs WHERE vs.scr = s.id)';
- my $q = $Multi::SQL->prepare('SELECT s.id'.$sql);
- $q->execute();
-
- my($bytes, $items, $id) = (0, 0, 0);
- while(($id) = $q->fetchrow_array) {
- my $f = sprintf '%s/%02d/%d.jpg', $_[HEAP]{sfpath}, $id%100, $id;
- my $t = sprintf '%s/%02d/%d.jpg', $_[HEAP]{stpath}, $id%100, $id;
- $bytes += -s $f;
- $bytes += -s $t;
- $items++;
- unlink $f;
- unlink $t;
- $_[KERNEL]->call(core => log => 3, 'Removing screenshot #%d', $id);
- }
-
- $Multi::SQL->do('DELETE'.$sql);
- $_[KERNEL]->call(core => log => 2, 'Removed %d unused screenshots, total of %.2fMB freed.',
- $items, $bytes/1024/1024) if $items;
- $_[KERNEL]->call(core => log => 2, 'No unused screenshots found') if !$items;
- $_[KERNEL]->yield('scr_finish');
-}
+# non-POE helper function
+sub do_resize { # im, [ maxwidth, maxheight ]
+ my($im, $dim) = @_;
-sub scr_finish { # [id]
- if($_[ARG0]) {
- $_[HEAP]{todo} = [ grep $_!=$_[ARG0], @{$_[HEAP]{todo}} ];
- return $_[KERNEL]->yield(scr_process => $_[HEAP]{todo}[0])
- if @{$_[HEAP]{todo}};
+ my($w, $h) = ($im->Get('width'), $im->Get('height'));
+ $dim = [ $w, $h ] if !$dim;
+ my($ow, $oh) = ($w, $h);
+ if($w > $$dim[0] || $h > $$dim[1]) {
+ if($w/$h > $$dim[0]/$$dim[1]) { # width is the limiting factor
+ $h *= $$dim[0]/$w;
+ $w = $$dim[0];
+ } else {
+ $w *= $$dim[1]/$h;
+ $h = $$dim[1];
+ }
}
+ $im->Thumbnail(width => $w, height => $h);
- $_[KERNEL]->post(core => finish => $_[HEAP]{curcmd});
- delete @{$_[HEAP]}{qw| curcmd todo |};
+ return ([$ow, $oh], [$w, $h]);
}
-
1;