[Rt-commit] rt branch, 4.2/subsample-logo, created. rt-4.2.5-100-gd5d9ff7

Alex Vandiver alexmv at bestpractical.com
Tue Jul 1 14:56:15 EDT 2014


The branch, 4.2/subsample-logo has been created
        at  d5d9ff796e1c3fc2701c5b818668bc22ef5c854d (commit)

- Log -----------------------------------------------------------------
commit 8cf72c60b28d8c26ff78e3b8eb9a1a1a62dfb485
Author: Alex Vandiver <alexmv at bestpractical.com>
Date:   Mon May 12 13:56:27 2014 -0400

    Don't sample every pixel of large logos
    
    The analyze_img code examined every pixel of the image; for large
    images, this caused the page to time out, thus making it impossible to
    change the image away from the problematically-large one.
    
    Subsample the image if it is more than 200px on a side, by sampling in
    an even 200x200 grid.  200px was chosen as an arbitrary upper limit; 40k
    points is still a large number to sample, but in testing can be done in
    less than 10s.
    
    Fixes #29929.

diff --git a/share/html/Admin/Tools/Theme.html b/share/html/Admin/Tools/Theme.html
index 87ea09e..f96556a 100644
--- a/share/html/Admin/Tools/Theme.html
+++ b/share/html/Admin/Tools/Theme.html
@@ -331,8 +331,20 @@ sub analyze_img {
     my $img = shift;
     my $color;
 
-    for my $i (0..$img->width-1) {
-        for my $j (0..$img->height-1) {
+    my @wsamples;
+    my @hsamples;
+    if ($img->width > 200) {
+        @wsamples = map { int($img->width*($_/200)) } (0..199);
+    } else {
+        @wsamples = ( 0 .. $img->width - 1 );
+    }
+    if ($img->height > 200) {
+        @hsamples = map { int($img->height*($_/200)) } (0..199);
+    } else {
+        @hsamples = ( 0 .. $img->height - 1 );
+    }
+    for my $i (@wsamples) {
+        for my $j (@hsamples) {
             my @color = $img->rgb( $img->getPixel($i,$j) );
             my $hsl = Convert::Color->new('rgb:'.join(',',map { $_ / 255 } @color))->convert_to('hsl');
             my $c = join(',', at color);

commit c6b3109196d968a2916dd061b0411b39091100f1
Author: Alex Vandiver <alexmv at bestpractical.com>
Date:   Mon May 12 14:26:21 2014 -0400

    gd_can need not be a global

diff --git a/share/html/Admin/Tools/Theme.html b/share/html/Admin/Tools/Theme.html
index f96556a..abe3bf3 100644
--- a/share/html/Admin/Tools/Theme.html
+++ b/share/html/Admin/Tools/Theme.html
@@ -61,7 +61,7 @@
     <label for="logo-upload"><&|/l&>Upload a new logo</&>:</label>
     <input type="file" name="logo-upload" id="logo-upload" /><br />
     <div class="gd-support">
-% if (%gd_can) {
+% if ($valid_image_types) {
     <&|/l, $valid_image_types &>Your system supports automatic color suggestions for: [_1]</&>
 % } else {
     <&|/l&>GD is disabled or not installed. You can upload an image, but you won't get automatic color suggestions.</&>
@@ -302,13 +302,13 @@ use List::MoreUtils qw(uniq);
 
 my $has_color_analyzer = eval { require Convert::Color; 1 };
 my $colors;
-my %gd_can;
 my $valid_image_types;
 
 if (not RT->Config->Get('DisableGD') and $has_color_analyzer) {
     require GD;
 
     # Always find out what GD can read...
+    my %gd_can;
     for my $type (qw(Png Jpeg Gif)) {
         $gd_can{$type}++ if GD::Image->can("newFrom${type}Data");
     }

commit 8a6fe3f7c2f82b2a6c5a70494428b98d32aabc16
Author: Alex Vandiver <alexmv at bestpractical.com>
Date:   Mon May 12 14:30:26 2014 -0400

    Do not install a subroutine into the HTML::Mason::Commands namespace
    
    sub {} in a Mason component makes the sub accessible to every Mason
    component, and is highly discouraged.  Use a local subref instead.

diff --git a/share/html/Admin/Tools/Theme.html b/share/html/Admin/Tools/Theme.html
index abe3bf3..c2e1e35 100644
--- a/share/html/Admin/Tools/Theme.html
+++ b/share/html/Admin/Tools/Theme.html
@@ -317,7 +317,7 @@ if (not RT->Config->Get('DisableGD') and $has_color_analyzer) {
     # ...but only analyze the image if we have data
     if ($imgdata) {
         if ( my $img = GD::Image->new($imgdata) ) {
-            $colors = analyze_img($img);
+            $colors = $analyze_img->($img);
         }
         else {
             # This has to be one damn long line because the loc() needs to be
@@ -327,7 +327,7 @@ if (not RT->Config->Get('DisableGD') and $has_color_analyzer) {
     }
 }
 
-sub analyze_img {
+my $analyze_img = sub {
     my $img = shift;
     my $color;
 
@@ -363,7 +363,7 @@ sub analyze_img {
         warn "bad";
     }
     return \@top5;
-}
+};
 </%INIT>
 <%ARGS>
 $user_css => ''

commit 65d5c641e23bbe57cd32e9d8916b0b1765e22ae7
Author: Alex Vandiver <alexmv at bestpractical.com>
Date:   Mon May 12 14:34:47 2014 -0400

    Replace a needless hashref with a plain hash

diff --git a/share/html/Admin/Tools/Theme.html b/share/html/Admin/Tools/Theme.html
index c2e1e35..542af44 100644
--- a/share/html/Admin/Tools/Theme.html
+++ b/share/html/Admin/Tools/Theme.html
@@ -329,7 +329,7 @@ if (not RT->Config->Get('DisableGD') and $has_color_analyzer) {
 
 my $analyze_img = sub {
     my $img = shift;
-    my $color;
+    my %colors;
 
     my @wsamples;
     my @hsamples;
@@ -349,16 +349,16 @@ my $analyze_img = sub {
             my $hsl = Convert::Color->new('rgb:'.join(',',map { $_ / 255 } @color))->convert_to('hsl');
             my $c = join(',', at color);
             next if $hsl->lightness < 0.1;
-            $color->{$c} ||= { h => $hsl->hue, s => $hsl->saturation, l => $hsl->lightness, cnt => 0, c => $c};
-            $color->{$c}->{cnt}++;
+            $colors{$c} ||= { h => $hsl->hue, s => $hsl->saturation, l => $hsl->lightness, cnt => 0, c => $c};
+            $colors{$c}->{cnt}++;
         }
     }
 
-    for (values %$color) {
+    for (values %colors) {
         $_->{rank} = $_->{s} * $_->{cnt};
     }
     my @top5 = grep { defined and $_->{'l'} and $_->{'c'} }
-                    (sort { $b->{rank} <=> $a->{rank} } values %$color)[0..5];
+                    (sort { $b->{rank} <=> $a->{rank} } values %colors)[0..5];
     if ((scalar uniq map {$_->{rank}} @top5) == 1) {
         warn "bad";
     }

commit 27963f709c2001236cb260fe70ca529577207bda
Author: Alex Vandiver <alexmv at bestpractical.com>
Date:   Mon May 12 14:36:15 2014 -0400

    Move List::MoreUtils closer to where it is used

diff --git a/share/html/Admin/Tools/Theme.html b/share/html/Admin/Tools/Theme.html
index 542af44..1f64d17 100644
--- a/share/html/Admin/Tools/Theme.html
+++ b/share/html/Admin/Tools/Theme.html
@@ -298,8 +298,6 @@ if (!$user_css) {
 
 # XXX: move this to some other modules
 
-use List::MoreUtils qw(uniq);
-
 my $has_color_analyzer = eval { require Convert::Color; 1 };
 my $colors;
 my $valid_image_types;
@@ -354,6 +352,7 @@ my $analyze_img = sub {
         }
     }
 
+    use List::MoreUtils qw(uniq);
     for (values %colors) {
         $_->{rank} = $_->{s} * $_->{cnt};
     }

commit 96488e7cf11cd1a4470ceb4a425bac2decc43868
Author: Alex Vandiver <alexmv at bestpractical.com>
Date:   Mon May 12 14:36:50 2014 -0400

    Remove an unnecessary warning triggered by single-colored logos

diff --git a/share/html/Admin/Tools/Theme.html b/share/html/Admin/Tools/Theme.html
index 1f64d17..37ab6d5 100644
--- a/share/html/Admin/Tools/Theme.html
+++ b/share/html/Admin/Tools/Theme.html
@@ -358,9 +358,6 @@ my $analyze_img = sub {
     }
     my @top5 = grep { defined and $_->{'l'} and $_->{'c'} }
                     (sort { $b->{rank} <=> $a->{rank} } values %colors)[0..5];
-    if ((scalar uniq map {$_->{rank}} @top5) == 1) {
-        warn "bad";
-    }
     return \@top5;
 };
 </%INIT>

commit b6f6e60ad32daddebd594814a61f6e51c2e642cc
Author: Alex Vandiver <alexmv at bestpractical.com>
Date:   Mon May 12 14:43:10 2014 -0400

    Move GD checking into $analyze_img

diff --git a/share/html/Admin/Tools/Theme.html b/share/html/Admin/Tools/Theme.html
index 37ab6d5..2fcd165 100644
--- a/share/html/Admin/Tools/Theme.html
+++ b/share/html/Admin/Tools/Theme.html
@@ -297,12 +297,12 @@ if (!$user_css) {
 }
 
 # XXX: move this to some other modules
-
-my $has_color_analyzer = eval { require Convert::Color; 1 };
 my $colors;
 my $valid_image_types;
+my $analyze_img = sub {
+    return undef if RT->Config->Get('DisableGD');
+    return undef unless eval { require Convert::Color; 1 };
 
-if (not RT->Config->Get('DisableGD') and $has_color_analyzer) {
     require GD;
 
     # Always find out what GD can read...
@@ -312,21 +312,18 @@ if (not RT->Config->Get('DisableGD') and $has_color_analyzer) {
     }
     $valid_image_types = join(", ", map { uc } sort { lc $a cmp lc $b } keys %gd_can);
 
+    my $imgdata = shift;
+    return undef unless $imgdata;
+
     # ...but only analyze the image if we have data
-    if ($imgdata) {
-        if ( my $img = GD::Image->new($imgdata) ) {
-            $colors = $analyze_img->($img);
-        }
-        else {
-            # This has to be one damn long line because the loc() needs to be
-            # source parsed correctly.
-            push @results, loc("Automatically suggested theme colors aren't available for your image. This might be because you uploaded an image type that your installed version of GD doesn't support. Supported types are: [_1]. You can recompile libgd and GD.pm to include support for other image types.", $valid_image_types);
-        }
+    my $img = GD::Image->new($imgdata);
+    unless ($img) {
+        # This has to be one damn long line because the loc() needs to be
+        # source parsed correctly.
+        push @results, loc("Automatically suggested theme colors aren't available for your image. This might be because you uploaded an image type that your installed version of GD doesn't support. Supported types are: [_1]. You can recompile libgd and GD.pm to include support for other image types.", $valid_image_types);
+        return undef;
     }
-}
 
-my $analyze_img = sub {
-    my $img = shift;
     my %colors;
 
     my @wsamples;
@@ -360,6 +357,7 @@ my $analyze_img = sub {
                     (sort { $b->{rank} <=> $a->{rank} } values %colors)[0..5];
     return \@top5;
 };
+$analyze_img->($imgdata);
 </%INIT>
 <%ARGS>
 $user_css => ''

commit 5fba328538f00f226d634a08b36aa211ed4e9624
Author: Alex Vandiver <alexmv at bestpractical.com>
Date:   Mon May 12 14:47:22 2014 -0400

    Move $analyze_img earlier

diff --git a/share/html/Admin/Tools/Theme.html b/share/html/Admin/Tools/Theme.html
index 2fcd165..5e52d8e 100644
--- a/share/html/Admin/Tools/Theme.html
+++ b/share/html/Admin/Tools/Theme.html
@@ -242,61 +242,6 @@ my $text_threshold = 0.6;
 my @results;
 my $imgdata;
 
-if (my $file_hash = _UploadedFile( 'logo-upload' )) {
-    my $my_system = RT::System->new( $session{CurrentUser} );
-    my ( $id, $msg ) = $my_system->SetAttribute(
-        Name        => "UserLogo",
-        Description => "User-provided logo",
-        Content     => {
-            type => $file_hash->{ContentType},
-            data => $file_hash->{LargeContent},
-            hash => md5_hex($file_hash->{LargeContent}),
-        },
-    );
-
-    push @results, loc("Unable to set UserLogo: [_1]", $msg) unless $id;
-
-    $imgdata = $file_hash->{LargeContent};
-}
-elsif ($ARGS{'reset_logo'}) {
-    RT->System->DeleteAttribute('UserLogo');
-}
-else {
-    if (my $attr = RT->System->FirstAttribute('UserLogo')) {
-        my $content = $attr->Content;
-        if (ref($content) eq 'HASH') {
-            $imgdata = $content->{data};
-        }
-        else {
-            RT->System->DeleteAttribute('UserLogo');
-        }
-    }
-}
-
-if ($user_css) {
-    if ($ARGS{'reset_css'}) {
-        RT->System->DeleteAttribute('UserCSS');
-        undef $user_css;
-    }
-    else {
-        my ($id, $msg) = RT->System->SetAttribute( Name => "UserCSS",
-                                                    Description => "User-provided css",
-                                                    Content => $user_css );
-        push @results, loc("Unable to set UserCSS: [_1]", $msg) unless $id;
-    }
-}
-
-if (!$user_css) {
-    my $attr = RT->System->FirstAttribute('UserCSS');
-    $user_css = $attr ? $attr->Content : join(
-        "\n\n" => map {
-            join "\n" => "/* ". $_->[0] ." */",
-                         map { "$_ {}" } @{$_->[1]}
-        } @sections
-    );
-}
-
-# XXX: move this to some other modules
 my $colors;
 my $valid_image_types;
 my $analyze_img = sub {
@@ -357,7 +302,61 @@ my $analyze_img = sub {
                     (sort { $b->{rank} <=> $a->{rank} } values %colors)[0..5];
     return \@top5;
 };
+
+if (my $file_hash = _UploadedFile( 'logo-upload' )) {
+    my $my_system = RT::System->new( $session{CurrentUser} );
+    my ( $id, $msg ) = $my_system->SetAttribute(
+        Name        => "UserLogo",
+        Description => "User-provided logo",
+        Content     => {
+            type => $file_hash->{ContentType},
+            data => $file_hash->{LargeContent},
+            hash => md5_hex($file_hash->{LargeContent}),
+        },
+    );
+
+    push @results, loc("Unable to set UserLogo: [_1]", $msg) unless $id;
+
+    $imgdata = $file_hash->{LargeContent};
+}
+elsif ($ARGS{'reset_logo'}) {
+    RT->System->DeleteAttribute('UserLogo');
+}
+else {
+    if (my $attr = RT->System->FirstAttribute('UserLogo')) {
+        my $content = $attr->Content;
+        if (ref($content) eq 'HASH') {
+            $imgdata = $content->{data};
+        }
+        else {
+            RT->System->DeleteAttribute('UserLogo');
+        }
+    }
+}
 $analyze_img->($imgdata);
+
+if ($user_css) {
+    if ($ARGS{'reset_css'}) {
+        RT->System->DeleteAttribute('UserCSS');
+        undef $user_css;
+    }
+    else {
+        my ($id, $msg) = RT->System->SetAttribute( Name => "UserCSS",
+                                                    Description => "User-provided css",
+                                                    Content => $user_css );
+        push @results, loc("Unable to set UserCSS: [_1]", $msg) unless $id;
+    }
+}
+
+if (!$user_css) {
+    my $attr = RT->System->FirstAttribute('UserCSS');
+    $user_css = $attr ? $attr->Content : join(
+        "\n\n" => map {
+            join "\n" => "/* ". $_->[0] ." */",
+                         map { "$_ {}" } @{$_->[1]}
+        } @sections
+    );
+}
 </%INIT>
 <%ARGS>
 $user_css => ''

commit d5d9ff796e1c3fc2701c5b818668bc22ef5c854d
Author: Alex Vandiver <alexmv at bestpractical.com>
Date:   Mon May 12 14:47:52 2014 -0400

    Cache the found colors in the logo attribute
    
    As determining these colors may be time-intensive, and is guaranteed to
    not change while the logo itself does not change, the information should
    simply be stored alongside the logo.

diff --git a/share/html/Admin/Tools/Theme.html b/share/html/Admin/Tools/Theme.html
index 5e52d8e..1f87127 100644
--- a/share/html/Admin/Tools/Theme.html
+++ b/share/html/Admin/Tools/Theme.html
@@ -304,6 +304,8 @@ my $analyze_img = sub {
 };
 
 if (my $file_hash = _UploadedFile( 'logo-upload' )) {
+    $colors = $analyze_img->($file_hash->{LargeContent});
+
     my $my_system = RT::System->new( $session{CurrentUser} );
     my ( $id, $msg ) = $my_system->SetAttribute(
         Name        => "UserLogo",
@@ -312,6 +314,7 @@ if (my $file_hash = _UploadedFile( 'logo-upload' )) {
             type => $file_hash->{ContentType},
             data => $file_hash->{LargeContent},
             hash => md5_hex($file_hash->{LargeContent}),
+            colors => $colors,
         },
     );
 
@@ -327,13 +330,25 @@ else {
         my $content = $attr->Content;
         if (ref($content) eq 'HASH') {
             $imgdata = $content->{data};
+            $colors = $content->{colors};
+            unless ($colors) {
+                # No colors cached; attempt to generate them
+                $colors = $content->{colors} = $analyze_img->($content->{data});
+                if ($content->{colors}) {
+                    # Found colors; update the attribute
+                    RT->System->SetAttribute(
+                        Name => "UserLogo",
+                        Description => "User-provided logo",
+                        Content => $content,
+                    );
+                }
+            }
         }
         else {
             RT->System->DeleteAttribute('UserLogo');
         }
     }
 }
-$analyze_img->($imgdata);
 
 if ($user_css) {
     if ($ARGS{'reset_css'}) {

-----------------------------------------------------------------------


More information about the rt-commit mailing list