Home | 簡體中文 | 繁體中文 | 雜文 | 知乎專欄 | Github | OSChina 博客 | 雲社區 | 雲棲社區 | Facebook | Linkedin | 視頻教程 | 打賞(Donations) | About
知乎專欄多維度架構 微信號 netkiller-ebook | QQ群:128659835 請註明“讀者”

2.6. 圖片尺寸優化與自動裁剪

http://netkiller.github.io/journal/image.html

2.6.1. 背景

某天我的前同事給我打電話,說他們的負載很高,經查發現網站首頁有20M,原因是首頁直接引用高清圖片,沒有安裝分辨率生成縮圖。於是我便想出了下面的方案。

我認為方案需求有如下幾個要素:

  1. 圖片壓縮

  2. 尺寸修改

  3. 圖片緩存

  4. 頻寬因素

例如用戶使用手機訪問網站,手機屏幕尺寸非常多樣化,常見的有QVGA(320×240)、HGVA(480×320)、WVGA(800×480)、QCIF(176×144)、SVGA(640x480)、WXGA(1280×800)。如果一個用戶的手機屏幕是320×240,打開網站後顯示1027*768圖片很不切合實際。同時用戶也多出不少頻寬開銷。

我們需要給用戶更好的體驗,就要多從用戶的角度去考慮,如根據用戶網速,頻寬,分辨率,為用戶提供更適合他終端的多媒體資源。

2.6.2. 實現思路

2.6.2.1. 尺寸動態變化

B/S結構應用程序無法獲取客戶端的分辨率等信息,我們將採用Javascript取出參數,然後告知伺服器端。

有下面幾種實現方式:

  1. 通過cookie

  2. post傳遞給伺服器,然後存儲在session中

  3. get 傳遞給伺服器,然後存儲在session中

僅舉一個例子

			
<script type="text/javascript">
$(function(){
    var width=window.screen.height;
    var height=window.screen.width;
    $.post('http://www.example.com/screen/resize.html',{w:width,h:height});
});
</script>
			
			

HTML頁面中的圖片的引用路徑

			
<img src="http://img.example.com/sample.jpg" />		
			
			

圖片伺服器rewrite處理

			
http://img.example.com/sample.jpg => http://img.example.com/index.php/sample.jpg		
			
			

index.php會首先載入sample.jpg檔案,然後綜合網速,頻寬,分辨率等因素,重新壓縮圖片,修改尺寸,發送mime頭,輸出正文。

2.6.2.2. 實時裁剪並靜態化

為了防止圖片地址衝突,我們首先需要URL唯一化,這樣每訪問一次會生成一張符合你需求尺寸的圖片。

http://img.example.com/sample_(width)x(height)_(quality).jpg

			
<img src="http://img.example.com/sample_1980x1080_100.jpg" />	
<img src="http://img.example.com/sample_800x600_80.jpg" />
<img src="http://img.example.com/sample_640x480_50.jpg" />
			
			

配置nginx通過try_files配置項可以實現檢查靜態檔案是否存在,如果不存在邊調用index.php生成圖片,當再次訪問時會直接讀取靜態檔案,不會再重新生成。

			
server {
    listen       80;
    server_name  inf.example.com;

    charset utf-8;
    access_log  /var/log/nginx/inf.example.com.access.log  main;
    error_log  /var/log/nginx/inf.example.com.error.log;

    location / {
        root   /www/example.com/inf.example.com/images;
        index  index.html;
		try_files $uri $uri/ /index.php?_url=$request_uri;
    }

    #error_page  404              /404.html;

    # redirect server error pages to the static page /50x.html
    #
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }

    # proxy the PHP scripts to Apache listening on 127.0.0.1:80
    #
    #location ~ \.php$ {
    #    proxy_pass   http://127.0.0.1;
    #}

    # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
    #
    location ~ /index\.php$ {
        root           html;
        fastcgi_pass   127.0.0.1:9000;
        fastcgi_index  index.php;
        fastcgi_param  SCRIPT_FILENAME  /www/example.com/inf.example.com/frontend/public$fastcgi_script_name;
        include        fastcgi_params;
    }

    # deny access to .htaccess files, if Apache's document root
    # concurs with nginx's one
    #
    location ~ /\.ht {
        deny  all;
    }
}			
			
			

通過這種方法還可以實現更複雜的需求,例如調整亮度,對比度,飽和度,色階,圖層疊加等等......

2.6.3. web或代理伺服器插件實現方案

首先我們要將分辨率參數放到cookie中,因為web伺服器是可以跟蹤cookie數據的

通過 web 擴展實現,例如我們開發一個apache插件,編譯後是".so"檔案,配置httpd.conf載入插件,插件具體功能是綜合網速,頻寬,分辨率等因素,重新壓縮圖片,修改尺寸,最後展現圖片。

反向代理與web伺服器實現原理相同