2012
Aug
02

網頁好讀版

GD Extension 主要功能是可以對圖片做處理,簡單的有圖片縮小、放大、切割,也可以用來製作圖片,這篇文章將會實做圖片的縮小,旋轉與銳利化。

Teajs GD Extension 安裝

要使用 Teajs 前,必須先安裝 GD Library , 先去下列的載點下載:GD_2_0_33

接著用 tar 解壓縮後,在 GD/src 目前下執行指令: cmake , 跑完之後再執行 make。

經過這兩步程式編譯就算完成了,最後把 libgd.so 搬到目錄 /usr/local/lib/ , 所有的 header 檔搬到 /usr/local/include/gd/ ,再執行 sudo ldconfig 即可。

如果上面的步驟一切正常,那麼我們就可以使用 GD library 了,不過這篇文章是要介紹如何使用 Teajs 的 GD , 所以得編譯完 Teajs 的 GD Extension才行。

進入 Teajs 的資料夾 src/lib/gd/, 再執行編譯指令↓

編譯 Teajs GD extension mode=compile g++ -Wall -O3 -fPIC -Dposix -DDSO_EXT=so -DREUSE_CONTEXT -shared -I. -DHAVE_CONFIG_H -g -O2 -I./../../ -I/usr/local/include/gd/ -lgd -c gd.cc -o ~/gd.o

g++ -shared -lgd -lpthread -lv8 -lrt -ldl -o gd.so ~/gd.o ../binary/bytestorage.os ../../common.os ../../app.os ../../path.os ../../cache.os

最後編譯出 gd.so 的 Teajs extension,再將 gd.so 搬到 Teajs extension 的目錄就大功告成囉,裝好之後我們就可以快樂的用 Javascript 來畫圖囉。

Javascript GD 畫圖!

在使用 GD 之前,我先來介紹一下圖片的類型,Teajs GD Extension 有支援三種圖片型態,分別是 JPEG,PNG, GIF ,這三種都是網路常見的圖片,所以也相當的夠用。

圖片Format 有二種, TrueColor 與 Palette , Palette 這個格式只能存 256 種顏色, 是 GIF 用的格式。

TrueColor 是一種由 32 bits 存儲的圖片格式,在三原色 RGB 中各用了 8個 bits ,每一個顏色可以存的數值是 0~255 ,這樣就有 2563 種組合,另外再配上「透明度 alpha」8 bits。

『jpeg』 使用的格式是 TrueColor , 『gif』使用的格式則是 Palette ,因此 gif 只有 256 種顏色可以使用,『png』則支援 TrueColor 與 Palette。

接下來我要做一個圖片Resize 的例子

縮圖前的阿蕯斯

縮圖後的阿蕯斯

Resize 程式範例

Resize.sjs
  1. var Image = require('gd').Image;
  2. var source = "Arthas-H.jpg";
  3. var img = resize(source , 100,150);
  4. img.save(Image.PNG , "tmp.png");
  5.  
  6. function resize(img ,to_w,to_h) {
  7. var pos = img.lastIndexOf('.');
  8. var ext = img.substring(pos+1, img.length);
  9. var type = Image.JPEG;
  10. switch(ext.toLowerCase()) {
  11. case 'jpeg':case 'jpg':
  12. type = Image.JPEG;
  13. break;
  14. case 'png':
  15. type = Image.PNG;
  16. break;
  17. case 'gif':
  18. type = Image.GIF;
  19. break;
  20.  
  21.  
  22. }
  23. var source_img = new Image(type , img);
  24. var w = source_img.sx();
  25. var h = source_img.sy();
  26. var image = new Image(Image.TRUECOLOR, to_w, to_h);
  27. var destx=0,desty=0;
  28. var srcx=0,srcy=0;
  29. image = image.copyResized(source_img, destx, desty, srcx, srcy, to_w, to_h , w , h );
  30. return image;
  31. }
  32.  

在 create Image 時,我使用了 TrueColor ,並載入一張 jpeg 型態的圖片,透過 copyResized method , 縮小圖片尺寸。

接下來是教學如果旋轉圖片,這裡會用到二維的『旋轉矩陣』與『三角函數』,先來看看旋轉的結果吧。

旋轉前的阿蕯斯

旋轉後的阿蕯斯

Rotate 旋轉原理

講到旋轉,就要先提到數學的座標軸轉換,首先我定義 θ1,(x1,y1) 為已知的一個點,θ2為我要旋轉的度,旋轉後我會得到 x2,y2的新座標,注意我這邊定義的旋轉是指逆時針旋轉。

# 數學上定義的旋轉,是指用座標軸逆時針旋轉 => 座標點為順時針旋轉 ,所以算出的結果有一丁點不同。

  • 圖中可以算半徑 z = x12+y12 的根號
  • x2 = z × cos(θ1+θ2) = z×(cosθ1×cosθ2 - sinθ1×sinθ2)
  • 因為 cosθ1 = x1/z , sinθ1 = y1/z
  • 得 x2 = x1×cosθ2 - y1×sinθ2
  • 一樣的算法可以求得 y2 = y1×cosθ2 + x1×sinθ2

算新座標點的位置,主要是為了計算圖片在旋轉之後,長度與寬度的改變,又因為圖片一定是長方形,左右兩邊是對稱的,所以只要算出右上角 point 的位移變化,就能得知左邊的點位移,知道點的位移後,就能得知長與寬的變化。

Rotate 圖片旋轉程式範例

Rotate.sjs
  1. var source = "Arthas-H.jpg";
  2. var img = rotate(source , 10);
  3. img.save(Image.PNG , "tmp.png");
  4.  
  5. function rotate(img , angle) {
  6. var PI = Math.PI;
  7. var radian = PI*angle/180;
  8. var pos = img.lastIndexOf('.');
  9. var ext = img.substring(pos+1, img.length);
  10. var type = Image.JPEG;
  11.  
  12. switch(ext.toLowerCase()) {
  13. case 'jpeg':case 'jpg':
  14. type = Image.JPEG;
  15. break;
  16. case 'png':
  17. type = Image.PNG;
  18. break;
  19. case 'gif':
  20. type = Image.GIF;
  21. break;
  22. }
  23. var source_img = new Image(type , img);
  24. var w = source_img.sx();
  25. var h = source_img.sy();
  26. var p2x = w/2, p2y = h/2;
  27. var diffw = Math.abs((p2x*Math.cos(radian) + p2y*Math.sin(radian))) - Math.abs(p2x);
  28. diffw = 2* Math.abs(diffw);
  29. var diffh = Math.abs(( -p2x*Math.sin(radian) + p2y*Math.cos(radian))) - Math.abs(p2y);
  30. diffh = 2* Math.abs(diffh);
  31.  
  32. var centerx = Math.round(w/2),centery = Math.round(h/2);
  33. var newH = h + diffh;
  34. var newW = w + diffw;
  35. var image = new Image(Image.TRUECOLOR, newW, newH);
  36. var destx=newW/2,desty=newH/2;//rotate in center
  37. var srcx=0,srcy=0;
  38. image = image.copyRotated(source_img, destx, desty, srcx, srcy, w, h , angle );
  39. return image;
  40. }
  41.  

接下來看看 sharpen 『銳利化』的功能

正常的阿蕯斯

銳利化後的阿蕯斯

銳利化程式範例

sharpen.sjs
  1. var img = sharpen(source, 150);
  2. img.save(Image.PNG , "tmp.png");
  3. function sharpen(img , percent) {
  4. var pos = img.lastIndexOf('.');
  5. var ext = img.substring(pos+1, img.length);
  6. var type = Image.JPEG;
  7.  
  8. switch(ext.toLowerCase()) {
  9. case 'jpeg':case 'jpg':
  10. type = Image.JPEG;
  11. break;
  12. case 'png':
  13. type = Image.PNG;
  14. break;
  15. case 'gif':
  16. type = Image.GIF;
  17. break;
  18. }
  19.  
  20. var source_img = new Image(type , img);
  21.  
  22. var data = source_img.sharpen(percent);
  23. return data;
  24. }
  25.  

網頁好讀版