国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專(zhuān)欄INFORMATION COLUMN

JavaScript中的圖片處理與合成(二)

hersion / 545人閱讀

摘要:通過(guò)這套流程,我們便能添加任意的圖片圖層并合成圖片。下篇文章,我們會(huì)繼續(xù)介紹下文字的合成和幾何圖片的合成,敬請(qǐng)期待

JavaScript中的圖片處理與合成(二) 引言

本系列分成以下4個(gè)部分:

基礎(chǔ)類(lèi)型圖片處理技術(shù)之縮放、裁剪與旋轉(zhuǎn)(傳送門(mén));

基礎(chǔ)類(lèi)型圖片處理技術(shù)之圖片合成;

基礎(chǔ)類(lèi)型圖片處理技術(shù)之文字合成;

算法類(lèi)型圖片處理技術(shù);

上篇文章,我們介紹了圖片的裁剪/旋轉(zhuǎn)與縮放,接下來(lái)本文主要介紹 圖片的合成 ,這是基礎(chǔ)類(lèi)圖片處理中比較實(shí)用且復(fù)雜的一部分,可以算第一篇文章內(nèi)容的實(shí)踐。

通過(guò)這些積累,我封裝了幾個(gè)項(xiàng)目中常用的功能:

圖片合成 ??? 圖片裁剪 ??? 人像摳除 圖片的合成

圖片的合成在實(shí)際項(xiàng)目中運(yùn)用也是十分的廣泛,大家可以試試這個(gè)demo(僅支持移動(dòng)端): ???

小狗貼紙

圖片的合成原理其實(shí)類(lèi)似于photoshop的理念,通過(guò) 圖層的疊加 ,最后合成并導(dǎo)出,相比于裁剪和縮放,其實(shí)基本原理是一致的,但是它涉及了更多的計(jì)算和比較復(fù)雜的流程,我們先一起來(lái)梳理下合成的整個(gè)邏輯。

相信大家對(duì) photoshop都是較為了解的,我們可以借鑒它的思維方式:

新建 psd 文件, 設(shè)置寬高;

設(shè)置背景圖;

從底部到頂部一層層添加所需要的圖層;

最后直接將整個(gè)文件導(dǎo)出成一張圖片;

以需要合成下圖為?:

1、首先我們需要?jiǎng)?chuàng)建一個(gè)與原圖一樣大小的畫(huà)布;

2、加載背景圖并 添加背景圖層 ,也就是這個(gè)美女啦~

3、加載貓耳朵圖并添加美女頭上的 貓耳朵圖層 ( 2/3順序不可逆,否則耳朵會(huì)被美女蓋在下面哦。因此圖片的加載控制十分重要 );

4、將整個(gè)畫(huà)布 導(dǎo)出圖片

合成部分,主要以封裝的插件為栗子哈。這樣能盡可能的完整,避免遺漏點(diǎn)。在開(kāi)始之前,為了確保圖片異步繪制的順序,我們需要先來(lái)構(gòu)建一套隊(duì)列系統(tǒng)。

隊(duì)列系統(tǒng);

圖片的加載時(shí)間是 異步且未知 的,而圖片的合成需要嚴(yán)格保證繪制 順序 ,越后繪制的圖片會(huì)置于越頂層,因此我們需要一套嚴(yán)格機(jī)制來(lái)控制圖片的加載與繪制,否則我們將無(wú)法避免的寫(xiě)出 回調(diào)地獄 ,這里我使用到了簡(jiǎn)單的隊(duì)列系統(tǒng);

隊(duì)列系統(tǒng)的原理其實(shí)也很簡(jiǎn)單,主要是為了我們能確保圖層從底到頂一層一層的繪制。我設(shè)計(jì)的使用方式如下, 隊(duì)列方式主要來(lái)確保add函數(shù)的按順序繪制:

// 創(chuàng)建畫(huà)布;
let mc = new MCanvas();

// 添加圖層;
mc.add(image-1).add(image-2);

// 繪制并導(dǎo)出圖片;
mc.draw();

這樣我們就明白了,這個(gè)隊(duì)列系統(tǒng)需要下面幾個(gè)點(diǎn):

queue隊(duì)列: 用于存放圖層繪制函數(shù);

next函數(shù): 用于表示當(dāng)前圖層已繪制完畢,執(zhí)行下一圖層的繪制;

add函數(shù): 作為統(tǒng)一添加圖層的方法,將繪制邏輯存入函數(shù)棧quene,并包裹next函數(shù);

draw函數(shù): 作為繪制啟動(dòng)函數(shù),表示所有圖層素材已經(jīng)準(zhǔn)備完畢,可以按順序開(kāi)始繪制;

MCanvas.queue = [];

MCanvas.prototype.add = function(){
    this.queue.push(()=>{
        // 繪制邏輯,之后詳解;
        ...
        
        // 執(zhí)行下個(gè)圖層繪制;
        this.next();
    });
}

MCanvas.prototype.next = function(){
    if(this.queue.length > 0){
            // 當(dāng)隊(duì)列中還有繪制任務(wù)時(shí),則推出并執(zhí)行;
        this.queue.shift()();
    }else{
            // 當(dāng)繪制完成后,調(diào)用成功事件,并傳出結(jié)果圖;
        this.fn.success();
    }
};

MCanvas.prototype.draw = function(){
    // 導(dǎo)出邏輯;
    ...
    
    // 設(shè)置成功事件,用于導(dǎo)出結(jié)果圖;    
    this.fn.success = () => {
         // 使用 setTimeout 能略微提升性能表現(xiàn);
         // 且隊(duì)列函數(shù)中都為真正的異步,因此此處不會(huì)影響邏輯;
        setTimeout(()=>{
            b64 = this.canvas.toDataURL(`image/jpeg}`, 0.9);
            
            ...
        },0);
   };
   
   // 啟動(dòng)隊(duì)列執(zhí)行;
    this.next();
}

此時(shí),queueaddnextdraw便組成了一整套隊(duì)列系統(tǒng),可確保圖片的順序加載和繪制,準(zhǔn)備好素材和隊(duì)列后,我們便可以開(kāi)始真正的合成圖片咯~~

創(chuàng)建畫(huà)布
MCanvas.prototype._init = function(){
    this.canvas = document.createElement("canvas");
    this.ctx = this.canvas.getContext("2d");
};
繪制背景圖

設(shè)置畫(huà)布大小并繪制美女背景圖。

通過(guò)調(diào)整背景圖的dx,dy,dw,dh參數(shù),可以繪制出多種模式,類(lèi)似于css中的background-sizecontain/cover等效果。

這里主要以上面使用到的場(chǎng)景為例子,既原圖模式。

// 原圖/效果圖尺寸保持一致;
MCanvas.prototype.background = function(image, bgOps){
    // 推入隊(duì)列系統(tǒng);
    this.queue.push(() => {
    let { iw, ih } = this._getSize(img);
        
    // 圖片與canvas的長(zhǎng)寬比;
    let iRatio = iw / ih;
        
    // 背景繪制參數(shù);
    let dx,dy,dwidth,dheight;
        
    // 設(shè)置畫(huà)布與背景圖尺寸一致;
    this.canvas.width = iw;
    this.canvas.height = ih;
    dx = dy = 0;
    dwidth = this.canvas.width;
    dheight = this.canvas.height;
        
    // 繪制背景圖;
    this.ctx.drawImage(img,dx,dy,dwidth,dheight);
        
    this._next(); 
    });
    return this;
};
繪制貓耳朵貼紙

相信大家都玩過(guò)貼紙,其最大的特點(diǎn),就是貼紙與背景圖的匹配。也就是用戶可以修改貼紙的 大小,位置,旋轉(zhuǎn)角度,通過(guò)手勢(shì)操作將貓耳朵完美地貼在照片人物的頭上。因此也就是說(shuō)add這個(gè)方法,需要設(shè)置縮放,旋轉(zhuǎn)與位置等參數(shù)。

這里先模擬出一份使用參數(shù), 實(shí)際真實(shí)情況會(huì)根據(jù)不同的背景圖,用戶會(huì)調(diào)整出不同的位置參數(shù)。

{
    // 圖片路徑;
    image:"./images/ear.png",
    options:{
        // 貼紙寬度;
        width:482,
        pos:{
            // 貼紙左上點(diǎn)坐標(biāo);
            x:150,
            y:58,
            // 貼紙放大系數(shù);
            scale:1,
            // 貼紙旋轉(zhuǎn)系數(shù);
            rotate:35,
        },
    },
}
add函數(shù)

接下里我們便來(lái)在add函數(shù)中解析下各個(gè)參數(shù)的使用姿勢(shì):

繪制小畫(huà)布來(lái)處理旋轉(zhuǎn):

// 創(chuàng)建小畫(huà)布;
let lcvs = document.createElement("canvas"),
    lctx = lcvs.getContext("2d");

// 貼紙圖原始大小;
let { iw, ih } = this._getSize(img);
// 繪制參數(shù);
let ldx, ldy, ldw, ldh;

// 貼紙?jiān)汲叽纾?ldw = iw;
ldh = ih;

// 繪制起始點(diǎn);
ldx = - Math.round(ldw / 2);
ldy = - Math.round(ldh / 2);

// 上篇文章我們說(shuō)過(guò)旋轉(zhuǎn)裁剪的問(wèn)題,這里就需要用到;
// 需要擴(kuò)大小畫(huà)布的容器,以避免旋轉(zhuǎn)造成的裁剪;最大值為放大5倍;
let _ratio = iw > ih ? iw / ih : ih / iw;
let lctxScale = _ratio * 1.4 > 5 ? 5 : _ratio * 1.4;

lcvs.width =  ldw * lctxScale;
lcvs.height = ldh * lctxScale;

// 調(diào)整繪制基點(diǎn);
lctx.translate(lcvs.width/2,lcvs.height/2);

// 旋轉(zhuǎn)畫(huà)板;
lctx.rotate(ops.pos.rotate);

// 繪制貼紙; 
lctx.drawImage(img,ldx,ldy,ldw,ldh);

此時(shí)我們會(huì)得到一個(gè)小畫(huà)布,中心繪制這貓耳朵貼紙:

接下來(lái)我們便是將貼紙繪制到背景圖上,需要注意的點(diǎn)就是,放大會(huì)增加貼紙畫(huà)布的空白區(qū)域,需要考慮到這部分區(qū)域,才能計(jì)算出最后真實(shí)的dx,dy值:

// 繪制參數(shù);
let cratio = iw / ih;
let cdx, cdy, cdw, cdh;

// ops.width 為最終畫(huà)到大畫(huà)布上時(shí)的寬度;
// 由于小畫(huà)布進(jìn)行了放大,因此最終寬度也需要等倍放大;
// 并乘以配置中還需要縮放的系數(shù);
cdw = ops.width * lctxScale * ops.pos.scale;
cdh = cdw / cratio * ops.pos.scale;

// 放大后增加的空白區(qū)域;
spaceX = (lctxScale - 1) * ops.width / 2;
spaceY = spaceX / cratio;

// 獲取素材的最終位置;
// 配置的位置 - 配置放大系數(shù)的影響 - 小畫(huà)布放大倍數(shù)的影響;
cdx = ops.pos.x + cdw * ( 1 - ops.pos.scale )/2 - spaceX;
cdy = ops.pos.y + cdh * ( 1 - ops.pos.scale )/2 - spaceY;

this.ctx.drawImage(lcvs,cdx,cdy,cdw,cdh);

lcvs = lctx = null;

這樣便能得到合成后的結(jié)果圖了,紅色邊框代表小畫(huà)布,黑色邊框代表大畫(huà)布:

MCanvas.prototype.add = function(img, options){
    this.queue.push(()=>{
        // 繪制貼紙小畫(huà)布;
        ...
        
        // 繪制貼紙到大畫(huà)布上;
        ...
        
        this._next();
    });
    
    return this;
}

這樣我們便完成了一系列方法,構(gòu)建了一套完整的合成流程。通過(guò)這套流程,我們便能添加任意的圖片圖層并合成圖片。

結(jié)語(yǔ)

本文主要講解了圖片合成上的方法原理和一些需要填的坑,這整套流程也是經(jīng)過(guò)了很長(zhǎng)一段時(shí)間的打磨,填了許多坑后總結(jié)出來(lái)的,算比較成熟的方案,已經(jīng)work在多個(gè)線上項(xiàng)目中,期望能對(duì)大家有所幫助!?。
下篇文章,我們會(huì)繼續(xù)介紹下文字的合成和幾何圖片的合成,敬請(qǐng)期待~~??

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/93183.html

相關(guān)文章

  • JavaScript中的圖片處理合成(一)

    摘要:中的圖片處理與合成一引言圖片處理現(xiàn)在已經(jīng)成為了我們生活中的剛需,想必大家也經(jīng)常有這方面的需求。實(shí)際前端業(yè)務(wù)中,也經(jīng)常會(huì)有很多的項(xiàng)目需要用到圖片加工和處理。 JavaScript中的圖片處理與合成(一) 引言: 圖片處理現(xiàn)在已經(jīng)成為了我們生活中的剛需,想必大家也經(jīng)常有這方面的需求。實(shí)際前端業(yè)務(wù)中,也經(jīng)常會(huì)有很多的項(xiàng)目需要用到圖片加工和處理。由于過(guò)去一段時(shí)間公司的業(yè)務(wù)需求,讓我在這方面積累...

    Charles 評(píng)論0 收藏0
  • JavaScript中的圖片處理合成(四)

    摘要:算法性能提升圖片算法處理實(shí)質(zhì)原理其實(shí)是遍歷像素點(diǎn),對(duì)像素點(diǎn)的值進(jìn)行改造。而像素點(diǎn)的數(shù)量與圖片的大小尺寸成正向指數(shù)級(jí)增長(zhǎng),因此適當(dāng)?shù)目s放圖片源后再去處理,對(duì)性能的提升十分巨大。 引言: 本系列現(xiàn)在構(gòu)思成以下4個(gè)部分: 基礎(chǔ)類(lèi)型圖片處理技術(shù)之縮放、裁剪與旋轉(zhuǎn)(傳送門(mén)); 基礎(chǔ)類(lèi)型圖片處理技術(shù)之圖片合成(傳送門(mén)); 基礎(chǔ)類(lèi)型圖片處理技術(shù)之文字合成(傳送門(mén)); 算法類(lèi)型圖片處理技術(shù)(傳送門(mén))...

    Coding01 評(píng)論0 收藏0
  • Webkit 渲染基礎(chǔ)硬件加速

    摘要:網(wǎng)頁(yè)的渲染方式主要有兩種軟件渲染和硬件加速渲染。而使用合成化的渲染技術(shù),以使用軟件繪圖的合成化渲染為例,對(duì)于使用繪制的層,其結(jié)果保存在內(nèi)存中,之后傳輸?shù)街羞M(jìn)行合成。 Webkit 渲染基礎(chǔ)與硬件加速 當(dāng)瀏覽器加載一個(gè) html 文件并對(duì)它進(jìn)行解析完畢后,內(nèi)核就會(huì)生成一個(gè)極為重要的數(shù)據(jù)結(jié)構(gòu)即 DOM 樹(shù),樹(shù)上每一個(gè)節(jié)點(diǎn)都對(duì)應(yīng)著網(wǎng)頁(yè)里面的某一個(gè)元素,并且開(kāi)發(fā)人員也可以通過(guò) JavaScri...

    ivan_qhz 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<