diff options
author | Yorhel <git@yorhel.nl> | 2009-07-18 20:31:50 +0200 |
---|---|---|
committer | Yorhel <git@yorhel.nl> | 2009-07-18 20:31:50 +0200 |
commit | ae53633780260b152a105c83fb4a7a72cd82d33b (patch) | |
tree | 4eafe357d9195c617e300ff1128ec87e336cf298 | |
parent | 5cbaaa3616a002a708af785bfa7e0774d50e0751 (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.
-rw-r--r-- | lib/Multi/Image.pm | 225 |
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; |