iT邦幫忙

2018 iT 邦幫忙鐵人賽
DAY 27
0
Modern Web

重新學習網頁設計系列 第 27

DAY 27. JavaScript Canvas 影像處理

DAY 27. JavaScript Canvas 影像處理

今天我們將認識如何操作Canvas的每個像素顏色。

drawImage

drawImage方法讓我們可以將影像繪至Canvas畫布上。

範例

首先介紹一個載入網址圖片的Promise函式drawImage
drawImage中,在圖片異步載入後使用Canvas方法drawImage方法將指定圖片畫至Canvas
接著回傳Canvas實例供我們操作,本篇內容將會使用到此函式。

function drawImage(imgURL) {
    return new Promise(resolve => {
        const img = new Image()
        img.crossOrigin = 'anonymous'
        img.addEventListener('load', e => {
            const canvas = document.createElement('canvas')
            const ctx = canvas.getContext('2d')

            // 將canvas尺寸設定與來源圖片一樣
            const width = img.width
            const height = img.height
            canvas.width = width
            canvas.height = height

            // 繪圖
            ctx.drawImage(img, 0, 0)
            resolve(canvas)
         })
        img.src = imgURL
    })
}

getImageData

getImageData方法用以取得CanvasImageData實例
ImageData的屬性data為畫布中像素的Buffer
通過修改這個Buffer,我們能夠實現真正的影像處理,意即實際操作每個像素的顏色。

putImageData

通過修改畫布的ImageData之後,接著需要使用putImageData方法更新畫布

範例

這個範例將會實現圖片Grayscale的效果

// 圖片來源: Google Image Search "apple"
const imgURL = 'http://juliandance.org/wp-content/uploads/2016/01/RedApple.jpg'
drawImage(imgURL).then(canvas => {
    const width = canvas.width
    const height = canvas.height
    const ctx = canvas.getContext('2d')
    const imageData = ctx.getImageData(0, 0, width, height)
    
    console.log(imageData)
    // [object ImageData] {
    //     data: [object Uint8ClampedArray],
    //     height: 456,
    //     width: 400
    // }

    const imageBuffer = imageData.data
    console.log(imageBuffer)    // [object Uint8ClampedArray]

    let red, green, blue, alpha;    // 定義各顏色的暫存變數
    let arg
    // 注意這裡的 i, 每次迭代時為 i += 4, 而非 i++
    for (let i = 0; i < imageBuffer.length; i += 4) {
        // 在imageBuffer之中每4個元素分別代表著每個像素的red, green, blue, alpha數值(0 ~ 255)
        red   = imageBuffer[i]
        green = imageBuffer[i + 1]
        blue  = imageBuffer[i + 2]
        alpha = imageBuffer[i + 3]

        // 將畫布中每個像素的rgb值設定為rgb平均值,能使圖片灰階化
        arg = (red + green + blue) / 3
        imageBuffer[i] = arg 
        imageBuffer[i + 1] = arg
        imageBuffer[i + 2] = arg
        imageBuffer[i + 3] = alpha
    }
    ctx.putImageData(imageData, 0, 0)
    document.body.appendChild(canvas)
})

JSBin Demo

請注意Demo中由於圖片來源並未設定允許跨域
因此Chrome瀏覽時必須搭配插件 cross-origin 才能正確看到結果。

本篇主題有幾個重點需特別注意

  • 圖片來源如果是跨域,載入時要設定img.crossOrigin = 'anonymous', 否則無法用於drawImage
  • 使用getImageData取得CanvasImageData實例,最後在處理完相術後要使用putImageData更新Canvas

上一篇
DAY 26. JavaScript Canvas 操作(二)
下一篇
DAY 28. JavaScript Canvas 動畫
系列文
重新學習網頁設計30

尚未有邦友留言

立即登入留言