fu: Close-up of Fu, bringing a scoop of water to her mouth (Default)
fu ([personal profile] fu) wrote in [site community profile] changelog2010-09-08 06:42 am

[dw-free] cleaning up userpics code

[commit: http://hg.dwscoalition.org/dw-free/rev/b29d6cfc5a83]

http://bugs.dwscoalition.org/show_bug.cgi?id=513

Move icon resizing code to the LJ::Userpic package.

Patch by [personal profile] kareila.

Files modified:
  • bin/worker/userpic-resize-gm
  • cgi-bin/LJ/Userpic.pm
  • cgi-bin/ljuserpics.pl
  • htdocs/editicons.bml
  • htdocs/misc/mogupic.bml
  • htdocs/tools/userpicfactory.bml
--------------------------------------------------------------------------------
diff -r 62e8e4716e81 -r b29d6cfc5a83 bin/worker/userpic-resize-gm
--- a/bin/worker/userpic-resize-gm	Wed Sep 08 14:21:07 2010 +0800
+++ b/bin/worker/userpic-resize-gm	Wed Sep 08 14:41:32 2010 +0800
@@ -26,6 +26,6 @@ sub lj_upf_resize {
 sub lj_upf_resize {
     my $job = shift;
     my $args = eval { Storable::thaw($job->arg) } || [];
-    return Storable::nfreeze(LJ::_get_upf_scaled(@$args));
+    return Storable::nfreeze( LJ::Userpic->_get_upf_scaled( @$args ) );
 }
 
diff -r 62e8e4716e81 -r b29d6cfc5a83 cgi-bin/LJ/Userpic.pm
--- a/cgi-bin/LJ/Userpic.pm	Wed Sep 08 14:21:07 2010 +0800
+++ b/cgi-bin/LJ/Userpic.pm	Wed Sep 08 14:41:32 2010 +0800
@@ -711,6 +711,184 @@ sub create {
     return $upic;
 }
 
+# this will return a user's userpicfactory image stored in mogile scaled down.
+# if only $size is passed, will return image scaled so the largest dimension will
+# not be greater than $size. If $x1, $y1... are set then it will return the image
+# scaled so the largest dimension will not be greater than 100
+# all parameters are optional, default size is 640.
+#
+# if maxfilesize option is passed, get_upf_scaled will decrease the image quality
+# until it reaches maxfilesize, in kilobytes. (only applies to the 100x100 userpic)
+#
+# returns [imageref, mime, width, height] on success, undef on failure.
+#
+# note: this will always keep the image's original aspect ratio and not distort it.
+sub get_upf_scaled {
+    my ( $class, @args ) = @_;
+
+    my $gc = LJ::gearman_client();
+
+    # no gearman, do this in-process
+    return $class->_get_upf_scaled( @args ) unless $gc;
+
+    # invoke gearman
+    my $u = LJ::get_remote() or die "No remote user";
+    unshift @args, "userid" => $u->id;
+
+    my $result;
+    my $arg = Storable::nfreeze(\@args);
+    my $task = Gearman::Task->new('lj_upf_resize', \$arg,
+                                  {
+                                      uniq => '-',
+                                      on_complete => sub {
+                                          my $res = shift;
+                                          return unless $res;
+                                          $result = Storable::thaw($$res);
+                                      }
+                                  });
+
+    my $ts = $gc->new_task_set();
+    $ts->add_task($task);
+    $ts->wait(timeout => 30); # 30 sec timeout;
+
+    # job failed ... error reporting?
+    die "Could not resize image down\n" unless $result;
+
+    return $result;
+}
+
+# actual method
+sub _get_upf_scaled
+{
+    my ( $class, %opts ) = @_;
+    my $size = delete $opts{size} || 640;
+    my $x1 = delete $opts{x1};
+    my $y1 = delete $opts{y1};
+    my $x2 = delete $opts{x2};
+    my $y2 = delete $opts{y2};
+    my $border = delete $opts{border} || 0;
+    my $maxfilesize = delete $opts{maxfilesize} || 38;
+    my $u = LJ::want_user(delete $opts{userid} || delete $opts{u}) || LJ::get_remote();
+    my $mogkey = delete $opts{mogkey};
+    my $downsize_only = delete $opts{downsize_only};
+    croak "No userid or remote" unless $u || $mogkey;
+
+    $maxfilesize *= 1024;
+
+    croak "Invalid parameters to get_upf_scaled\n" if scalar keys %opts;
+
+    my $mode = ($x1 || $y1 || $x2 || $y2) ? "crop" : "scale";
+
+    eval "use Image::Magick (); 1;"
+        or return undef;
+
+    eval "use Image::Size (); 1;"
+        or return undef;
+
+    $mogkey ||= 'upf:' . $u->{userid};
+    my $dataref = LJ::mogclient()->get_file_data($mogkey) or return undef;
+
+    # original width/height
+    my ($ow, $oh) = Image::Size::imgsize($dataref);
+    return undef unless $ow && $oh;
+
+    # converts an ImageMagick object to the form returned to our callers
+    my $imageParams = sub {
+        my $im = shift;
+        my $blob = $im->ImageToBlob;
+        return [\$blob, $im->Get('MIME'), $im->Get('width'), $im->Get('height')];
+    };
+
+    # compute new width and height while keeping aspect ratio
+    my $getSizedCoords = sub {
+        my $newsize = shift;
+
+        my $fromw = $ow;
+        my $fromh = $oh;
+
+        my $img = shift;
+        if ($img) {
+            $fromw = $img->Get('width');
+            $fromh = $img->Get('height');
+        }
+
+        return (int($newsize * $fromw/$fromh), $newsize) if $fromh > $fromw;
+        return ($newsize, int($newsize * $fromh/$fromw));
+    };
+
+    # get the "medium sized" width/height.  this is the size which
+    # the user selects from
+    my ($medw, $medh) = $getSizedCoords->($size);
+    return undef unless $medw && $medh;
+
+    # simple scaling mode
+    if ($mode eq "scale") {
+        my $image = Image::Magick->new(size => "${medw}x${medh}")
+            or return undef;
+        $image->BlobToImage($$dataref);
+        unless ($downsize_only && ($medw > $ow || $medh > $oh)) {
+            $image->Resize(width => $medw, height => $medh);
+        }
+        return $imageParams->($image);
+    }
+
+    # else, we're in 100x100 cropping mode
+
+    # scale user coordinates  up from the medium pixelspace to full pixelspace
+    $x1 *= ($ow/$medw);
+    $x2 *= ($ow/$medw);
+    $y1 *= ($oh/$medh);
+    $y2 *= ($oh/$medh);
+
+    # cropping dimensions from the full pixelspace
+    my $tw = $x2 - $x1;
+    my $th = $y2 - $y1;
+
+    # but if their selected region in full pixelspace is 800x800 or something
+    # ridiculous, no point decoding the JPEG to its full size... we can
+    # decode to a smaller size so we get 100px when we crop
+    my $min_dim = $tw < $th ? $tw : $th;
+    my ($decodew, $decodeh) = ($ow, $oh);
+    my $wanted_size = 100;
+    if ($min_dim > $wanted_size) {
+        # then let's not decode the full JPEG down from its huge size
+        my $de_scale = $wanted_size / $min_dim;
+        $decodew = int($de_scale * $decodew);
+        $decodeh = int($de_scale * $decodeh);
+        $_ *= $de_scale foreach ($x1, $x2, $y1, $y2);
+    }
+
+    $_ = int($_) foreach ($x1, $x2, $y1, $y2, $tw, $th);
+
+    # make the pristine (uncompressed) 100x100 image
+    my $timage = Image::Magick->new(size => "${decodew}x${decodeh}")
+        or return undef;
+    $timage->BlobToImage($$dataref);
+    $timage->Scale(width => $decodew, height => $decodeh);
+
+    my $w = ($x2 - $x1);
+    my $h = ($y2 - $y1);
+    my $foo = $timage->Mogrify(crop => "${w}x${h}+$x1+$y1");
+
+    my $targetSize = $border ? 98 : 100;
+
+    my ($nw, $nh) = $getSizedCoords->($targetSize, $timage);
+    $timage->Scale(width => $nw, height => $nh);
+
+    # add border if desired
+    $timage->Border(geometry => "1x1", color => 'black') if $border;
+
+    foreach my $qual (qw(100 90 85 75)) {
+        # work off a copy of the image so we aren't recompressing it
+        my $piccopy = $timage->Clone();
+        $piccopy->Set('quality' => $qual);
+        my $ret = $imageParams->($piccopy);
+        return $ret if length(${ $ret->[0] }) < $maxfilesize;
+    }
+
+    return undef;
+}
+
 # make this picture the default
 sub make_default {
     my $self = shift;
diff -r 62e8e4716e81 -r b29d6cfc5a83 cgi-bin/ljuserpics.pl
--- a/cgi-bin/ljuserpics.pl	Wed Sep 08 14:21:07 2010 +0800
+++ b/cgi-bin/ljuserpics.pl	Wed Sep 08 14:41:32 2010 +0800
@@ -354,186 +354,5 @@ sub get_picid_from_keyword
     return $default;
 }
 
-# this will return a user's userpicfactory image stored in mogile scaled down.
-# if only $size is passed, will return image scaled so the largest dimension will
-# not be greater than $size. If $x1, $y1... are set then it will return the image
-# scaled so the largest dimension will not be greater than 100
-# all parameters are optional, default size is 640.
-#
-# if maxfilesize option is passed, get_upf_scaled will decrease the image quality
-# until it reaches maxfilesize, in kilobytes. (only applies to the 100x100 userpic)
-#
-# returns [imageref, mime, width, height] on success, undef on failure.
-#
-# note: this will always keep the image's original aspect ratio and not distort it.
-sub get_upf_scaled {
-    my @args = @_;
-
-    my $gc = LJ::gearman_client();
-
-    # no gearman, do this in-process
-    return LJ::_get_upf_scaled(@args)
-        unless $gc;
-
-    # invoke gearman
-    my $u = LJ::get_remote()
-        or die "No remote user";
-    unshift @args, "userid" => $u->id;
-
-    my $result;
-    my $arg = Storable::nfreeze(\@args);
-    my $task = Gearman::Task->new('lj_upf_resize', \$arg,
-                                  {
-                                      uniq => '-',
-                                      on_complete => sub {
-                                          my $res = shift;
-                                          return unless $res;
-                                          $result = Storable::thaw($$res);
-                                      }
-                                  });
-
-    my $ts = $gc->new_task_set();
-    $ts->add_task($task);
-    $ts->wait(timeout => 30); # 30 sec timeout;
-
-    # job failed ... error reporting?
-    die "Could not resize image down\n" unless $result;
-
-    return $result;
-}
-
-# actual method
-sub _get_upf_scaled
-{
-    my %opts = @_;
-    my $size = delete $opts{size} || 640;
-    my $x1 = delete $opts{x1};
-    my $y1 = delete $opts{y1};
-    my $x2 = delete $opts{x2};
-    my $y2 = delete $opts{y2};
-    my $border = delete $opts{border} || 0;
-    my $maxfilesize = delete $opts{maxfilesize} || 38;
-    my $u = LJ::want_user(delete $opts{userid} || delete $opts{u}) || LJ::get_remote();
-    my $mogkey = delete $opts{mogkey};
-    my $downsize_only = delete $opts{downsize_only};
-    croak "No userid or remote" unless $u || $mogkey;
-
-    $maxfilesize *= 1024;
-
-    croak "Invalid parameters to get_upf_scaled\n" if scalar keys %opts;
-
-    my $mode = ($x1 || $y1 || $x2 || $y2) ? "crop" : "scale";
-
-    eval "use Image::Magick (); 1;"
-        or return undef;
-
-    eval "use Image::Size (); 1;"
-        or return undef;
-
-    $mogkey ||= 'upf:' . $u->{userid};
-    my $dataref = LJ::mogclient()->get_file_data($mogkey) or return undef;
-
-    # original width/height
-    my ($ow, $oh) = Image::Size::imgsize($dataref);
-    return undef unless $ow && $oh;
-
-    # converts an ImageMagick object to the form returned to our callers
-    my $imageParams = sub {
-        my $im = shift;
-        my $blob = $im->ImageToBlob;
-        return [\$blob, $im->Get('MIME'), $im->Get('width'), $im->Get('height')];
-    };
-
-    # compute new width and height while keeping aspect ratio
-    my $getSizedCoords = sub {
-        my $newsize = shift;
-
-        my $fromw = $ow;
-        my $fromh = $oh;
-
-        my $img = shift;
-        if ($img) {
-            $fromw = $img->Get('width');
-            $fromh = $img->Get('height');
-        }
-
-        return (int($newsize * $fromw/$fromh), $newsize) if $fromh > $fromw;
-        return ($newsize, int($newsize * $fromh/$fromw));
-    };
-
-    # get the "medium sized" width/height.  this is the size which
-    # the user selects from
-    my ($medw, $medh) = $getSizedCoords->($size);
-    return undef unless $medw && $medh;
-
-    # simple scaling mode
-    if ($mode eq "scale") {
-        my $image = Image::Magick->new(size => "${medw}x${medh}")
-            or return undef;
-        $image->BlobToImage($$dataref);
-        unless ($downsize_only && ($medw > $ow || $medh > $oh)) {
-            $image->Resize(width => $medw, height => $medh);
-        }
-        return $imageParams->($image);
-    }
-
-    # else, we're in 100x100 cropping mode
-
-    # scale user coordinates  up from the medium pixelspace to full pixelspace
-    $x1 *= ($ow/$medw);
-    $x2 *= ($ow/$medw);
-    $y1 *= ($oh/$medh);
-    $y2 *= ($oh/$medh);
-
-    # cropping dimensions from the full pixelspace
-    my $tw = $x2 - $x1;
-    my $th = $y2 - $y1;
-
-    # but if their selected region in full pixelspace is 800x800 or something
-    # ridiculous, no point decoding the JPEG to its full size... we can
-    # decode to a smaller size so we get 100px when we crop
-    my $min_dim = $tw < $th ? $tw : $th;
-    my ($decodew, $decodeh) = ($ow, $oh);
-    my $wanted_size = 100;
-    if ($min_dim > $wanted_size) {
-        # then let's not decode the full JPEG down from its huge size
-        my $de_scale = $wanted_size / $min_dim;
-        $decodew = int($de_scale * $decodew);
-        $decodeh = int($de_scale * $decodeh);
-        $_ *= $de_scale foreach ($x1, $x2, $y1, $y2);
-    }
-
-    $_ = int($_) foreach ($x1, $x2, $y1, $y2, $tw, $th);
-
-    # make the pristine (uncompressed) 100x100 image
-    my $timage = Image::Magick->new(size => "${decodew}x${decodeh}")
-        or return undef;
-    $timage->BlobToImage($$dataref);
-    $timage->Scale(width => $decodew, height => $decodeh);
-
-    my $w = ($x2 - $x1);
-    my $h = ($y2 - $y1);
-    my $foo = $timage->Mogrify(crop => "${w}x${h}+$x1+$y1");
-
-    my $targetSize = $border ? 98 : 100;
-
-    my ($nw, $nh) = $getSizedCoords->($targetSize, $timage);
-    $timage->Scale(width => $nw, height => $nh);
-
-    # add border if desired
-    $timage->Border(geometry => "1x1", color => 'black') if $border;
-
-    foreach my $qual (qw(100 90 85 75)) {
-        # work off a copy of the image so we aren't recompressing it
-        my $piccopy = $timage->Clone();
-        $piccopy->Set('quality' => $qual);
-        my $ret = $imageParams->($piccopy);
-        return $ret if length(${ $ret->[0] }) < $maxfilesize;
-    }
-
-    return undef;
-}
-
-
 1;
 
diff -r 62e8e4716e81 -r b29d6cfc5a83 htdocs/editicons.bml
--- a/htdocs/editicons.bml	Wed Sep 08 14:21:07 2010 +0800
+++ b/htdocs/editicons.bml	Wed Sep 08 14:41:32 2010 +0800
@@ -200,7 +200,7 @@ use strict;
                 return $err->("Invalid userpic creation parameters.") if (!$scaledsizemax || !$x2);
 
                 my $picinfo = eval {
-                    LJ::get_upf_scaled(
+                    LJ::Userpic->get_upf_scaled(
                         x1 => $x1,
                         y1 => $y1,
                         x2 => $x2,
@@ -802,7 +802,7 @@ sub parse_post_uploads
                             }
                             
                             eval {
-                                my $picinfo = LJ::get_upf_scaled(
+                                my $picinfo = LJ::Userpic->get_upf_scaled(
                                     size => 100,
                                     u    => $u,
                                     mogkey => "upf_${counter}:$u->{userid}"
diff -r 62e8e4716e81 -r b29d6cfc5a83 htdocs/misc/mogupic.bml
--- a/htdocs/misc/mogupic.bml	Wed Sep 08 14:21:07 2010 +0800
+++ b/htdocs/misc/mogupic.bml	Wed Sep 08 14:41:32 2010 +0800
@@ -28,7 +28,7 @@ _c?><?_code
     my $size = int($GET{'size'});
     $size = 640 if $size <= 0 || $size > 640;
 
-    my $upf = LJ::get_upf_scaled(size => $size, userid => $u->id, mogkey => "upf_$GET{index}:$u->{userid}");
+    my $upf = LJ::Userpic->get_upf_scaled( size => $size, userid => $u->id, mogkey => "upf_$GET{index}:$u->{userid}" );
 
     return $ML{'.error.image'} unless $upf;
 
diff -r 62e8e4716e81 -r b29d6cfc5a83 htdocs/tools/userpicfactory.bml
--- a/htdocs/tools/userpicfactory.bml	Wed Sep 08 14:21:07 2010 +0800
+++ b/htdocs/tools/userpicfactory.bml	Wed Sep 08 14:41:32 2010 +0800
@@ -42,7 +42,7 @@ _c?>
 
     if (!$w || !$h) {
         # we do not have the width and height passed in, we have to compute it ourselves
-        my $upf = LJ::get_upf_scaled(size => $scaledSizeMax, userid => $remote->{userid}, mogkey => "upf_$GET{index}:$remote->{userid}");
+        my $upf = LJ::Userpic->get_upf_scaled( size => $scaledSizeMax, userid => $remote->userid, mogkey => "upf_$GET{index}:$remote->{userid}" );
         ($w, $h) = ($upf->[2], $upf->[3]) if ($upf && $upf->[2]);
     }
 
--------------------------------------------------------------------------------