Changeset 1155


Ignore:
Timestamp:
11/12/11 17:18:55 (6 months ago)
Author:
adrian.budau
Message:

Avatar Optimization

This is an optimization for managing avatars on the server. Because
there are only 5 sizes used on all the site it's more useful to resize
all of the images to those 5(thus increasing the space usage by less
than 100%) and when a client asks for a size give it directly rather
then resizing all the time. The 5 sizes are tiny (old L16x16),
small(old L32x32), normal(old L50x50), forum(old L75xL75, used only on

the forum at the moment), big(old 100x100) and full(the original picture).


To get the avatar on a size from the server simply use the page
avatar/%some_size%/%some_user where %some_user% is a username and
%some_size$ is a one the 5 sizes. In case the user doesn't exists or he
doesn't have an avatar we use a placeholder image. If the size given is
not from the list or is omitted the server return a classic
404 Error(File not found)

The script which resizes the image for the current users is called
make-avatar-folder found in the scripts folder. It requires the attach
folder to have permission for read and write.

The setup has also been modified so fresh installes will work without
calling the script.

Reviewboard Link: http://reviewboard.infoarena.ro/r/176/

Location:
trunk
Files:
3 added
13 edited

Legend:

Unmodified
Added
Removed
  • trunk/common/attachment.php

    r1115 r1155  
    146146} 
    147147 
     148/** 
     149 * Resizes an image whose filepath is given by the parameters into a new 
     150 * location specified by the other parameters 
     151 * 
     152 * Returns whether or not the image has been successfully resized 
     153 * Note that it returns false if the image doesn't have a known file-type 
     154 * 
     155 * The $new_filepath parameter if ommited or given as null will result in the 
     156 * image being outputted directly to the client 
     157 * 
     158 * @param  array   $image_info         An array containing information about the 
     159 *                                     original image: width, height, mime-type 
     160 * @param  string  $filepath 
     161 * @param  array   $new_image_info     An array containing the new width and 
     162 *                                     height 
     163 * @param  string  $new_filepath 
     164 * @return bool 
     165 */ 
     166function image_resize($image_info, $filepath, $new_image_info, 
     167        $new_filepath = null) { 
     168    list($image_width, $image_height, $image_type, $image_attribute) = $image_info; 
     169    list($new_image_width, $new_image_height) = $new_image_info; 
     170 
     171    switch ($image_type) { 
     172        case IMAGETYPE_GIF: 
     173            // NOTE: animated GIFs become static. Only the first frame is saved 
     174            // Seems like a good thing anyway 
     175            $image = imagecreatefromgif($filepath); 
     176            $image_resized = imagecreate($new_image_width, $new_image_height); 
     177            // reset palette and transparent color to that of the original file 
     178            $trans_col = imagecolortransparent($image); 
     179            imagepalettecopy($image_resized, $image); 
     180            imagefill($image_resized, 0, 0, $trans_col); 
     181            imagecolortransparent($image_resized, $trans_col); 
     182            imagecopyresampled($image_resized, $image, 0, 0, 0, 0, 
     183                    $new_image_width, $new_image_height, $image_width, 
     184                    $image_height); 
     185 
     186            if ($new_filepath != null) { 
     187                return imagegif($image_resized, $new_filepath); 
     188            } 
     189            return imagegif($image_resized); 
     190 
     191        case IMAGETYPE_JPEG: 
     192            $image = imagecreatefromjpeg($filepath); 
     193            $image_resized = imagecreatetruecolor($new_image_width, 
     194                    $new_image_height); 
     195            imagecopyresampled($image_resized, $image, 0, 0, 0, 0, 
     196                    $new_image_width, $new_image_height, $image_width, 
     197                    $image_height); 
     198 
     199            if ($new_filepath != null) { 
     200                return imagejpeg($image_resized, $new_filepath); 
     201            } 
     202            return imagejpeg($image_resized); 
     203 
     204        case IMAGETYPE_PNG: 
     205            $image = imagecreatefrompng($filepath); 
     206            $image_resized = imagecreatetruecolor($new_image_width, 
     207                    $new_image_height); 
     208            // turn off the alpha blending to keep the alpha channel 
     209            imagealphablending($image_resized, false); 
     210            // allocate transparent color 
     211            $col = imagecolorallocatealpha($image_resized, 0, 0, 0, 127); 
     212            // fill the image with the new color 
     213            imagefilledrectangle($image_resized, 0, 0, $new_image_width, 
     214                    $new_image_height, $col); 
     215            imagecopyresampled($image_resized, $image, 0, 0, 0, 0, 
     216                    $new_image_width, $new_image_height, $image_width, 
     217                    $image_height); 
     218            imagesavealpha($image_resized, true); 
     219            if ($new_filepath != null) { 
     220                return imagepng($image_resized, $new_filepath); 
     221            } 
     222            return imagepng($image_resized); 
     223 
     224        default: 
     225            // unsupported image type 
     226            return false; 
     227    } 
     228} 
    148229?> 
  • trunk/common/common.php

    r1083 r1155  
    260260function is_taggable($obj) { 
    261261    return $obj == 'user' || $obj == 'task' || $obj == 'round' || $obj == 'textblock'; 
     262} 
     263 
     264/** 
     265 * Returns whether or not the size type given is an existent one on the site 
     266 * 
     267 * @param  string  $size_type 
     268 * @return bool 
     269 */ 
     270function is_valid_size_type($size_type) { 
     271    $size_types = array("full", "tiny", "small", "normal", "forum", "big"); 
     272    return in_array($size_type, $size_types); 
    262273} 
    263274 
  • trunk/common/db/user.php

    r1110 r1155  
    168168{ 
    169169    log_assert_valid(user_validate($user)); 
    170      
     170 
    171171    // Update DB 
    172172    db_update("ia_user", $user, "id = ".db_quote($user['id'])); 
  • trunk/config.php.sample

    r1085 r1155  
    3232// Slashes at both ends. 
    3333define("IA_URL_PREFIX", "--write-me-IA_URL_PREFIX--"); 
     34 
     35// Define the place the avatars are being stored 
     36define("IA_AVATAR_FOLDER", "--write-me-IA_AVATAR_FOLDER--"); 
    3437 
    3538 
  • trunk/scripts/setup

    r1021 r1155  
    135135 
    136136// Ask user. 
    137 $config_vars['IA_ROOT_DIR'] = read_line("SVN checkout dir?", $config_vars['IA_ROOT_DIR']); 
     137$config_vars['IA_ROOT_DIR'] = read_line("SVN checkout dir?", 
     138        $config_vars['IA_ROOT_DIR']); 
    138139$config_vars['IA_ROOT_DIR'] = slash_string( 
    139140        realpath($config_vars['IA_ROOT_DIR']), true, true); 
     141$config_vars['IA_AVATAR_FOLDER'] = 
     142        $config_vars['IA_ROOT_DIR'].'www/static/images/avatar/'; 
     143$config_vars['IA_AVATAR_FOLDER'] = read_line("Avatar Folder?", 
     144        $config_vars['IA_AVATAR_FOLDER']); 
     145$config_vars['IA_AVATAR_FOLDER'] = slash_string( 
     146        realpath($config_vars['IA_AVATAR_FOLDER']), true, true); 
    140147$config_vars['IA_URL_HOST'] = read_line("Host part of url (with http)?", 
    141148        $config_vars['IA_URL_HOST']); 
     
    223230    system("chmod g+ws {$ia_root}attach"); 
    224231    system("chmod g+ws {$ia_root}cache"); 
     232    system("chmod g+ws {$ia_root}www/static/images/avatar"); 
    225233    system("chmod g+ws {$ia_root}www/static/images/tmp"); 
    226234    system("chmod g+ws {$ia_root}www/static/images/latex"); 
  • trunk/smf/Sources/Load.php

    r1154 r1155  
    10051005 
    10061006        // use infoarena avatars 
    1007         $avatar_img_src = url_user_avatar($profile['memberName'], '75x75', true); 
     1007        $avatar_img_src = url_user_avatar($profile['memberName'], 'forum', true); 
    10081008 
    10091009        // What a monstrous array... 
  • trunk/www/controllers/account.php

    r1069 r1155  
    44require_once(IA_ROOT_DIR."common/db/attachment.php"); 
    55require_once(IA_ROOT_DIR."common/db/smf.php"); 
     6require_once(IA_ROOT_DIR."common/avatar.php"); 
    67require_once(IA_ROOT_DIR."www/controllers/account_validator.php"); 
     8require_once(IA_ROOT_DIR."www/config.php"); 
    79 
    810// identify target user and check permission to edit profile 
     
    131133                        $errors['avatar'] = 'Fisierul nu a putut fi incarcat ' 
    132134                                            .'pe server.'; 
     135                    } else { 
     136                        // resize the avatar if it is a correct mime-type 
     137                        global $IA_SAFE_MIME_TYPES; 
     138                        $img_info = getimagesize($disk_name); 
     139                        // check if mime-type is from accepted ones 
     140                        if (in_array($img_info['mime'], $IA_SAFE_MIME_TYPES)) { 
     141                            avatar_cache_resized($disk_name, $img_info, 
     142                                    "a".$user['username']); 
     143                        } 
    133144                    } 
    134145                } 
  • trunk/www/controllers/image_attachment.php

    r923 r1155  
    7070    // Image is placed in output buffer, cached, then flushed. 
    7171    ob_start(); 
    72     switch ($img_type) { 
    73         case IMAGETYPE_GIF: 
    74             // NOTE: animated GIFs become static. Only the first frame is saved 
    75             // Seems like a good thing anyway 
    76             $im = imagecreatefromgif($real_name); 
    77             $im_resized = imagecreate($new_width, $new_height); 
    78             // reset palette and transparent color to that of the original file 
    79             $trans_col = imagecolortransparent($im); 
    80             imagepalettecopy($im_resized, $im); 
    81             imagefill($im_resized, 0, 0, $trans_col); 
    82             imagecolortransparent($im_resized, $trans_col); 
    83             imagecopyresampled($im_resized, $im, 0, 0, 0, 0, $new_width, $new_height, $img_width, $img_height); 
    84             imagegif($im_resized); 
    85             break; 
     72    $image_supported = image_resize($ret, $real_name, array($new_width, $new_height)); 
    8673 
    87         case IMAGETYPE_JPEG: 
    88             $im = imagecreatefromjpeg($real_name); 
    89             $im_resized = imagecreatetruecolor($new_width, $new_height); 
    90             imagecopyresampled($im_resized, $im, 0, 0, 0, 0, $new_width, $new_height, $img_width, $img_height); 
    91             imagejpeg($im_resized); 
    92             break; 
    93  
    94         case IMAGETYPE_PNG: 
    95             $im = imagecreatefrompng($real_name); 
    96             $im_resized = imagecreatetruecolor($new_width, $new_height); 
    97             // turn off the alpha blending to keep the alpha channel 
    98             imagealphablending($im_resized, false); 
    99             // allocate transparent color 
    100             $col = imagecolorallocatealpha($im_resized, 0, 0, 0, 127); 
    101             // fill the image with the new color 
    102             imagefilledrectangle($im_resized, 0, 0, $new_width, $new_height, $col); 
    103             imagecopyresampled($im_resized, $im, 0, 0, 0, 0, $new_width, $new_height, $img_width, $img_height); 
    104             imagesavealpha($im_resized, true); 
    105             imagepng($im_resized); 
    106             break; 
    107  
    108         default: 
    109             ob_end_clean(); 
    110             // unsupported image type 
    111             die_http_error(500, "Unsupported image type"); 
     74    if ($image_supported == false) { 
     75        ob_end_clean(); 
     76        die_http_error(500, "Unsupported image"); 
    11277    } 
    11378 
     
    12085    header("Content-Type: " . image_type_to_mime_type($img_type)); 
    12186    header("Content-Disposition: inline; filename=" . urlencode($file_name) . ";"); 
    122     // WARNING: strlen() is supposed to be binary safe but some say it may  
     87    // WARNING: strlen() is supposed to be binary safe but some say it may 
    12388    // be shadowed by mb_strlen() and treat strings as unicode by default, 
    12489    // thus reporting invalid lengths for random binary buffers. 
  • trunk/www/format/format.php

    r1105 r1155  
    130130 
    131131// Format avatar img. 
    132 function format_user_avatar($user_name, $width = 50, $height = 50, 
     132function format_user_avatar($user_name, $size_type = "full", 
    133133                            $absolute = false) 
    134134{ 
    135     log_assert(is_whole_number($width), "Invalid width"); 
    136     log_assert(is_whole_number($height), "Invalid height"); 
    137     $url = url_user_avatar($user_name, "L{$width}x{$height}"); 
     135    log_assert(is_valid_size_type($size_type), "Invalid size type"); 
     136    $url = url_user_avatar($user_name, $size_type); 
    138137    if ($absolute) { 
    139138        $url = url_absolute($url); 
     
    166165    $result .= "<span class=\"tiny-user\">"; 
    167166    $result .= format_link($user_url, 
    168                            format_user_avatar($user_name, 16, 16, false).$user_fullname, 
     167                           format_user_avatar($user_name, "tiny", false).$user_fullname, 
    169168                           false); 
    170169    $result .= ' '.$rbadge; 
     
    188187    $result .= "<div class=\"normal-user\">"; 
    189188    $result .= format_link($user_url, 
    190                            format_user_avatar($user_name, 32, 32, false), 
     189                           format_user_avatar($user_name, "small", false), 
    191190                           false); 
    192191    $result .= "<span class=\"fullname\">$user_fullname</span><br />"; 
  • trunk/www/htaccess.sample

    r980 r1155  
    1212RewriteCond %{REQUEST_URI}  !^.*/stiri/.*$ 
    1313RewriteCond %{REQUEST_URI}  !^.*/news_feed$ 
     14RewriteCond %{REQUEST_URI}  !^.*/avatar/.*$ 
    1415RewriteRule ^(.*) index.php?page=$1 [QSA] 
     16 
     17RewriteRule ^avatar/(tiny|small|normal|forum|big|full)/(.+)$ static/images/avatar/$1/a$2 
     18RewriteCond %{REQUEST_FILENAME} !-f 
     19RewriteCond %{REQUEST_FILENAME} !-d 
     20RewriteRule ^static/images/avatar/(tiny|small|normal|forum|big|full)/(.+)$ static/images/avatar/$1/noimage 
     21 
    1522RewriteRule ^stiri/(.*)$ blog/$1 [R=301,QSA] 
    1623RewriteRule ^news_feed$ blog?action=rss [R=301,QSA] 
  • trunk/www/url.php

    r1132 r1155  
    239239} 
    240240 
    241 function url_user_avatar($username, $resize = "50x50") { 
    242     return url_image_resize(IA_USER_TEXTBLOCK_PREFIX . $username, 'avatar', $resize); 
     241/** 
     242 * Returns an url to an user's avatar with a given size 
     243 * 
     244 * @param  string  $username 
     245 * @param  string  $size_type 
     246 * @return string 
     247 */ 
     248function url_user_avatar($username, $size_type = "full") { 
     249    return url_complex("avatar/".$size_type."/".$username); 
    243250} 
    244251 
  • trunk/www/views/account.php

    r1149 r1155  
    9292            <?php 
    9393                // display avatar 
    94                 $avatar_url = url_user_avatar($user['username'], "150x150"); 
     94                $avatar_url = url_user_avatar($user['username'], "big"); 
    9595                echo '<img class="avatar" src="'.html_escape($avatar_url).'" alt="avatar"/>'; 
    9696            ?> 
  • trunk/www/views/sitewide.php

    r1064 r1155  
    1616    <?php if (!identity_is_anonymous()) { $username = $identity_user['username']; ?> 
    1717        <div id="userbox"> 
    18         <?= format_link(url_user_profile($username, true), format_user_avatar($username, 50, 50, true), false) ?> 
     18        <?= format_link(url_user_profile($username, true), format_user_avatar($username, "normal", true), false) ?> 
    1919            <div class="user"> 
    2020                <strong><?= html_escape($identity_user['full_name']) ?></strong><br/> 
Note: See TracChangeset for help on using the changeset viewer.