Image
圖片。
Pixel
一張電腦圖片、一幅螢幕畫面、一臺電子跑馬燈,都是由許多小光點組成,一個小光點就是一個「像素」、「畫素」。大量的小光點排列整齊,宛如棋盤方格,構成一張「圖片」。
如果我們把小光點弄得夠小夠密集,或者相對來說,讓小光點離我們很遠很渺小,那麼觀看圖片時,相鄰的小光點就會糊在一起,彷彿是柔順平滑的圖片。
在電腦當中,是以 0 到 255 的整數數值,表示小光點的亮度。 0 是最暗, 255 是最亮。 256 種數值已經足夠細膩,超越人類視覺對於亮度的辨別能力!
Red, Green, Blue, Alpha
一個像素擁有三個數值,分別代表紅光、綠光、藍光的亮度。這三個數值簡稱 RGB ,分別是紅、綠、藍的第一個英文字母。
三種光的數值都是 255 ,疊合之後就是白光、呈現白色。三種光的數值都是 0 ,就是無光、呈現黑色。三種光的數值都一樣,則呈現灰色。三種光的數值不一樣,則呈現各式各樣的彩色。
第一張圖片是範例圖片;第二張圖片是保留 R 值,而 G 值與 B 值設定為 0 ;第三張圖片是保留 G 值;第四張圖片是保留 B 值。右邊三張圖片的對應像素相加之後,就會形成左圖。
有些圖片額外增加一個數值,代表透明程度。這個數值簡稱 A ,是 alpha 的第一個英文字母。
0 是完全透明、呈現背景底色; 255 是完全不透明、呈現圖片原色;其餘數值則是依照比重混合圖片原色與背景底色。
左圖所有像素的 A 值都是 255 ,完全不透明,看不到網頁背景的顏色;中圖所有像素的 A 值是 127 ,透明的程度是 50% ,看得到一點網頁背景的顏色;右圖中央 A 值高、外圍 A 值低。
Image 的資料結構
二維陣列相當適合作為圖片的資料結構。
const int X = 1024 , Y = 768 ;
struct Color {unsigned char r , g , b ;};
Color image [Y ][X ];
void drawPixel (int x , int y , Color color )
{
image [y ][x ] = color ;
}
bool onImage (int x , int y )
{
return x >= 0 && x < X && y >= 0 && y < Y ;
}
void initImage ()
{
memset (image , 0xff , sizeof (image ));
}
注意到:存取矩陣元素、存取圖片像素,行列順序剛好顛倒。套用圖片函式庫時,要尤其小心。
電視機與相機經常強調畫素與解析度。畫素很高,意思是小光點很多;解析度很高,意思是小光點很密,使得圖片清晰銳利。
延伸閱讀:使用 C/C++ 處理圖片
C 與 C++ 本身沒有處理圖片的函式庫。
你可以土法煉鋼,參考 BMP 、 JPEG 、 PNG 的規格書,自己寫程式讀取圖片擷取像素;然後利用 Windows API 、
Linux 視窗介面的工具 、 Cocoa ,自己寫程式把圖片像素畫在螢幕上。
你也可以拍手煉成,直接拿現成的函式庫來用,例如 CImg 、 OpenCV ,都是不錯的選擇。
延伸閱讀:使用 Qt/C#/Java 處理圖片
這些語言處理圖片的方式都大同小異。首先建立一個圖片物件( Qt 的 QImage 、 C# 的 Image 、 Java 的 Image 與 ImageIO ),然後建立一個視窗,覆寫視窗的重繪函式,取其繪圖物件( Qt 的 QPaint 、 C# 的 Graphics 、 Java 的 Graphics ),把圖片畫在視窗當中。
延伸閱讀:使用 HTML 與 JavaScript 處理圖片
將圖片畫在網頁上,只消幾行程式碼。首先在 HTML 當中,建立一個 <img> 以及一個 <canvas> 。然後在 JavaScript 當中,利用 drawImage() 將 <img> 的圖片畫在 <canvas> 上面。
也可以利用 createElement() ,動態建立 <img> 與 <canvas> 。圖片的部分,也可以利用 Image() 建構子,動態建立 <img> 。
<canvas id ="canvas1" ></canvas >
<img src ="img.png" id ="img1" style ="display:none;" >
<script >
var canvas = document .getElementById ("canvas1" );
var ctx = canvas .getContext ("2d" );
var img = document .getElementById ("img1" );
ctx .drawImage (img , 0 , 0 );
</script >
我們無法直接從 <img> 得到像素。必須先將 <img> 的圖片畫在 <canvas> 上面,再利用 getImageData() 得到像素。其成員 .data 是一條一維陣列,依序存放每個像素的 RGBA 值。
修改好每個像素的數值之後,最後利用 putImageData() 將像素畫在 <canvas> 上面,便大功告成了。
<canvas id ="canvas1" ></canvas >
<img src ="img.png" id ="img1" style ="display:none;" >
<script >
var canvas = document .getElementById ('canvas1' );
var ctx = canvas .getContext ('2d' );
var img = document .getElementById ('img1' );
ctx .drawImage (img , 0 , 0 );
var w = img .naturalWidth ;
var h = img .naturalHeight ;
var imgdt = ctx .getImageData (0 , 0 , w , h );
var a = imgdt .data ;
for (var k =0 ; k <a .length ; k +=4 )
{
a [k ] = 255 - a [k ];
a [k +1 ] = 255 - a [k +1 ];
a [k +2 ] = 255 - a [k +2 ];
a [k +3 ] = 255 ;
}
canvas .width = w ;
canvas .height = h ;
ctx .putImageData (imgdt , 0 , 0 );
</script >
想要宣告像素,可以利用 createImageData() 。想要拷貝像素,可以直接拷貝陣列。
var imgdt2 = ctx .createImageData (w , h );
var a2 = imgdt2 .data ;
var imgdt2 = ctx .createImageData (w , h );
var a2 = new Uint8ClampedArray (imgdt .data );
imgdt2 .data .set (a2 );
學會擷取像素之後,就能做一些簡單的實驗了,例如顛倒色彩( 255 減掉原本的數值)、彩色變灰階( RGB 相加除以三)、失焦模糊(取鄰近像素求平均值)。
甚至可以即時處理影片。影片可以想成是很多張圖片組成的。
延伸閱讀:使用 Photoshop/GIMP 處理圖片
只要發揮創意,就能做出各種圖片特效。完全不需要學習程式語言與數學,只需要仔細閱讀軟體使用說明書。
VIDEO
留言