HT for Web基於HTML5的圖像操做(一)

HT for Web首創的矢量圖片設計架構,使其具備強大豐富的動態圖形呈現能力,但從最近知乎熱議的「Adobe Photoshop 是否已通過時?」的話題,你們能體會到不少狀況下實際項目不可能徹底採用矢量,項目中仍是有大量的傳統非矢量的靜態圖片,畢竟工具強大且現有資源豐富,但爲了使靜態圖片呈現出更多的動態效果,HT for Web提供了較多渲染方式,例如對HT for Web的圖元設置‘body.color’的style後圖元便可達到自動染色的效果,這裏將對這種染色技術進行講解。html

Screen Shot 2014-11-22 at 7.26.24 PM

上圖呈現了本文例子最終的呈現效果,中間爲原始圖片是http://hightopo.com/images/banner.png ,對其分別設置了紅、黃和藍三種顏色後的染色效果,徹底基於HT for Web實現這麼個簡單拓撲的話代碼不過十多行,不過今天咱們不借助HT for Web提供的‘body.color’的染色功能,咱們將採用最原始的方式生產染色圖片。node

dataModel = new ht.DataModel();                   
    graphView = new ht.graph.GraphView(dataModel); 
    graphView.addToDOM();
    var root = new ht.Node();
    root.setImage('ht-for-web.png');
    dataModel.add(root);                                
    ['blue', 'yellow', 'red'].forEach(function(color){
        var node = new ht.Node();
        node.setImage('ht-for-web.png');
        node.s({ 'body.color': color });
        dataModel.add(node);             
        var edge = new ht.Edge(root, node);
        edge.s({'edge.color': color});
        dataModel.add(edge);                    
    });

染色的原理就是對圖片像素內容的操做,能夠理解爲一個 convertColor(r, c, rawColor, …)->finalColor 的像素函數轉換, 其中的r和c分別表明像素所在行和列,rawColor爲原始顏色信息,…表明其餘的參數信息,例如咱們進行染血的顏色信息,最終經過convertColor處理返回的finalColor爲轉換後的像素值。web

圖片染色操做能夠說是最簡單的圖像處理了,本質就是rawColor * tintColor,這裏的tintColor能夠理解爲HT for Web的body.color值,通常該信息表明監控系統的告警級別狀態等信息,經過染色讓用戶更直觀的觀察到設備運行告警狀態。這裏的rawColor * tintColor相乘是本質是分別對兩個顏色的rgb進行相乘,通常狀況下最後的alpha的透明度,會保持原始rawColor的值不進行操做處理。算法

    toRGBA = (function(){
        var map = {}, // string - [128,128,128,255]
            canvas;
        return function(color){
            var g, data = map[color];
            if (!data) {
                if(!canvas){
                    canvas = document.createElement('canvas'); 
                    canvas.width = 1;
                    canvas.height = 1;
                }
                g = canvas.getContext('2d');
                g.clearRect(0, 0, 1, 1);          
                g.fillStyle = color;
                g.beginPath();
                g.rect(0, 0, 1, 1);
                g.fill();                                                
                data = g.getImageData(0, 0, 1, 1).data;
                data = map[color] = [data[0], data[1], data[2], data[3]];
            }
            return data;           
        };
    })();            

    function init(){    
        var image = new Image();
        image.src = 'banner.png';// 'ht-for-web.png';
        image.onload = function(){
            dataModel = new ht.DataModel();                   
            graphView = new ht.graph.GraphView(dataModel); 
            graphView.addToDOM();

            var root = new ht.Node();
            root.setImage(image);
            dataModel.add(root);  

            ['blue', 'yellow', 'red'].forEach(function(color){
                var node = new ht.Node();
                node.setImage(createColorImage1(image, color));                        
                dataModel.add(node);             
                var edge = new ht.Edge(root, node);
                edge.s({
                    'edge.color': color
                });
                dataModel.add(edge);                    
            });                     
        };
    }
    function createColorImage1(image, color) {
        var width = image.width;
        var height = image.height;                
        var canvas = document.createElement('canvas');
        var context = canvas.getContext( "2d" );
        canvas.width = width;
        canvas.height = height;
        context.drawImage(image, 0, 0, width, height);                
        var rgba = toRGBA(color);
        var r = rgba[0]/255, g = rgba[1]/255, b = rgba[2]/255;
        var pixelData = context.getImageData(0, 0, width, height);
        var pixels = pixelData.data;
        for (var i = 0; i < pixels.length; i += 4)
        {
            pixels[i+0] *= r;
            pixels[i+1] *= g;
            pixels[i+2] *= b;
        }
        context.putImageData(pixelData, 0, 0);
        return canvas;
    }

以上代碼爲實現的所有邏輯,有兩點須要注意,顏色值經過getImageData返回的是0~255的值,進行染色相乘咱們須要基於0~1的格式,所以須要先除以255轉換後再相乘。另一點爲了方便用戶開發,顏色值容許是任意html支持的顏色格式,有可能輸入red,rgba(255,125,128,0.1)等格式,以上toRGBA代碼在閉包中返回了個可根據輸入格式返回顏色數組的工具函數,其藉助的也是在一個像素的canvas內存中動態繪製,再經過getImageData來決定顏色信息,再經過map緩存計算結果,這種方式比枚舉一堆顏色映射表來得精簡。canvas

固然採用這種染色算法在圖元是純黑色的時候是有問題的,由於黑色的rgb值都爲0,所以不管乘以什麼顏色結果也都爲0,實際應用場景能夠要求美工避免作純黑色的圖片,或者代碼對純黑色的圖片進行特殊的運算處理。數組

以上方式僅是第一種染色方式,所以爲createColorImage1,下篇將介紹第二種染色方式createColorImage2。緩存

Screen Shot 2014-11-22 at 8.23.41 PM

相關文章
相關標籤/搜索