天天看點

HTML5邊玩邊學(3):像素和顔色

提示:建議使用 Chrome 浏覽器或者 Firefox 浏覽器閱讀本文,否則文中的樣例程式可能無法看到運作效果。

一、了解顔色

我們在電腦螢幕上可以看到色彩斑斓的圖像,其實這些圖像都是由一個個像素點組成的。那麼像素是什麼?顔色又是什麼呢?(如果您提出這兩個問題,您一定是個熱愛思考的人)一個像素其實對應着記憶體中的一組連續的二進制位,由于是二進制位,每個位上的取值當然隻能是 0 或者 1 了!這樣,這組連續的二進制位就可以由 0 ,1 排列組合出很多種情況,而每一種排列組合就決定了這個像素的一種顔色。先看看下面這幅圖

我們可以看到這幅圖描述了六個像素點,一共由24個小方框組成。

注意:圖中的一個小方框代表一個位元組,即8個二進制位。

是以,每個像素點由四個位元組組成。圖中也分别标出了這四個位元組代表的含義:

第一個位元組決定像素的紅色值

第二個位元組決定像素的綠色值

第三個位元組決定像素的藍色值

第四個位元組決定像素的透明度值

每一種分顔色值的大小是從 0 到 255(提問:為什麼隻能到255?) ,透明度的取值:0 代表完全透明,255代表完全不透明

這樣,我們就可以用(255,0,0,255)來表示一個純紅色像素

在記憶體中,他是這樣的一個32位的串: 11111111 00000000 00000000 11111111

二、操作像素

了解了顔色和像素的實質,我們就可以對圖形進行更加複雜的處理。

可是,HTML5 目前還沒有提供類似 setPixel 或者 getPixel 這樣直接操作像素點的方法, 但是我們也有辦法

就是使用 ImageData 對象:

ImageData對象用來儲存圖像像素值,它有 width、height和 data 三個屬性,其中 data 屬性就是一個連續數組,圖像的所有像素值其實是儲存在 data 裡面的。

data 屬性儲存像素值的方法和我們在前面圖檔中看到的一模一樣:

imageData.data[index*4 +0]

imageData.data[index*4 +1]

imageData.data[index*4 +2]

imageData.data[index*4 +3]

上面取出了 data 數組中連續相鄰的四個值,這四個值分别代表了圖像中第 index+1 個像素的紅色、綠色、藍色和透明度值的大小。

注意:index 從0 開始,圖像中總共有 width * height 個像素,數組中總共儲存了 width * height * 4 個數值

上下文對象 Context 有三個方法用來建立、讀取和設定 ImageData 對象,他們分别是

createImageData(width, height):在記憶體中建立一個指定大小的 ImageData 對象(即像素數組),對象中的像素點都是黑色透明的,即rgba(0,0,0,0)

getImageData(x, y, width, height):傳回一個 ImageData 對象,這個 IamgeData 對象中包含了指定區域的像素數組

putImageData(data, x, y):将 ImageData 對象繪制到螢幕的指定區域上

三、一個簡單的圖像處理例子

上面說了這麼多,我們用了解的知識來玩玩圖像程式設計,或許有一天我們就要在 Chrome 中玩 PhotoShop 了。

程式大概是這個樣子的:

1、将一幅圖檔繪制到一個 canvas 元素上,為了不引發安全錯誤(Security_ERR:DOM EXCEPTION 18),我用的是我部落格頂部的橫幅背景圖檔。你要運作這個例子,可能需要改成自己的圖檔

2、有四個滑動條,分别代表 GRBA 四個分量

3、拖動滑動條,圖像中對應的顔色分量就會增加或者減少

4、如果圖像變成透明,就會顯示 canvas 元素的背景,我把這個背景設定成了我的頭像,呵呵。

思路:其實就是用 getImageData 方法,将你想改變的那一塊區域的像素數組取出來,然後根據你拖動的滑動條和滑動條的數值,來更改那一塊區域裡所有像素對應顔色分量的值。處理完畢後再用 putImageData 方法繪制到畫布上,就是這麼簡單。

下面是代碼:

簡單的圖像處理

<canvas id="test1" width="507" height="348" style="background-image:url(http://images.cnblogs.com/cnblogs_com/myqiao/262115/r_2204793492575248335.jpg)">你的浏覽器不支援 <canvas>标簽,請使用 Chrome 浏覽器 或者 FireFox 浏覽器</canvas>

紅色:<input type="range" min="1" max="100" onchange="colorChange(event,0)"/>

綠色:<input type="range" min="1" max="100" onchange="colorChange(event,1)"/>

藍色:<input type="range" min="1" max="100" onchange="colorChange(event,2)"/>

透明:<input type="range" min="1" max="100" onchange="colorChange(event,3)"/>

<script type="text/javascript">

    //擷取上下文對象

    var canvas = document.getElementById("test1");

    var ctx = canvas.getContext("2d");

    //畫布的寬度和長度

    var width = parseInt(canvas.getAttribute("width"));

    var height = parseInt(canvas.getAttribute("height"));

    //裝入圖像

    var image = new Image();

    image.onload =imageLoaded;

    //頂部背景圖檔

    image.src = "/skins/Valentine/images/banner2.gif";

    //用來儲存像素數組的變量

    var imageData=null;

    function imageLoaded() {

        // 将圖檔畫到畫布上

        ctx.drawImage(image, 0, 0);

        //取圖像的像素數組

        imageData = ctx.getImageData(0, 0, width, height);

    }

    function colorChange(event,offset){

        imageLoaded();

        for (var y = 0; y < imageData.height; y++) {

            for (x = 0;x < imageData.width; x++) {

                //index 為目前要處理的像素編号

                var index = y * imageData.width + x;

                //一個像素占四個位元組,即 p 為目前指針的位置

                var p = index * 4;

                //改變目前像素 offset 顔色分量的數值,offset 取值為0-3

                var color = imageData.data[p + offset] * event.target.value / 50; 

                // 顔色值限定在[0..255]

                color = Math.min(255, color); 

                //将改變後的顔色值存回數組

                imageData.data[p + offset]=color

            }

        }

        //輸出到螢幕

        ctx.putImageData(imageData, 0, 0);

</script>

你的浏覽器不支援 <canvas>标簽,請使用 Chrome 浏覽器 或者 FireFox 浏覽器

紅色:

綠色:

藍色:

透明:

四、繪制随機顔色的點

這個例子是在畫布上随機選擇一個點,然後再給他一個随機的顔色值,其實用到的方法和上面的例子大同小異,就是需求不同罷了。

下面是代碼和程式執行個體:

随機顔色的點

<canvas id="test2" width="300" height="300" style=" background-color: black">你的浏覽器不支援 <canvas>标簽,請使用 Chrome 浏覽器 或者 FireFox 浏覽器</canvas>

<input type="button" value="畫随機點" onclick="interval=setInterval(randomPixel,1);" />

<input type="button" value="停止" onclick="clearInterval(interval);"/>

<input type="button" value="清除" onclick="clearCanvas();"/>

    var canvas = document.getElementById("test2");

    var imageData = ctx.createImageData(width, height);

    function randomPixel(){

        var x= parseInt(Math.random()*width);

        var y= parseInt(Math.random()*height);

        var index = y * width + x;

        var p = index * 4;

        imageData.data[p + 0] = parseInt(Math.random() * 256);

        imageData.data[p + 1] = parseInt(Math.random() * 256);

        imageData.data[p + 2] = parseInt(Math.random() * 256);

        imageData.data[p + 3] =parseInt(Math.random() * 256);

        ctx.putImageData(imageData,0,0);

    function clearCanvas(){

        ctx.clearRect(0,0,width,height);

        imageData = ctx.createImageData(width, height);

下面是前兩篇的連結:

<a href="http://www.cnblogs.com/myqiao/archive/2010/09/17/1829639.html" target="_blank">HTML5邊玩邊學(1):畫布</a>

<a href="http://www.cnblogs.com/myqiao/archive/2010/09/18/1830041.html" target="_blank">HTML5邊玩邊學(2):基礎繪圖</a>

//==================================================

本文轉自左洸部落格園部落格,原文連結:http://www.cnblogs.com/myqiao/archive/2010/09/18/1830460.html,如需轉載請自行聯系原作者

繼續閱讀