1. 程式人生 > 其它 >基於ArkUI開發框架,圖片馬賽克處理的實現

基於ArkUI開發框架,圖片馬賽克處理的實現

  關於馬賽克   馬賽克是一種使用較為廣泛的圖片處理方式,通過將圖片特定區域的色階細節劣化、色塊打亂讓圖片模糊化,常用來遮擋圖片中的重要資訊及隱私內容。本期,我們將通過影象的基礎知識幫助大家瞭解圖片馬賽克處理的原理,同時給大家帶來ArkUI開發框架中圖片馬賽克處理的實現。     一、影象基礎   瞭解圖片的畫素以及解析度等基礎知識,有助於後文對馬賽克原理的理解。   1. 畫素 畫素(英文名:pixel,簡稱px)是圖片的最小單位,每張圖片都是由無數的畫素點組成。如圖1所示,每個小方格就是一個個的畫素點,每個畫素點都具有明確的位置座標和色彩數值,畫素點的位置和顏色共同決定該圖片所呈現出來的樣子。   圖1 畫素點
  在計算機中,每個畫素點的色彩數值都是通過RGB通道來控制,RGB即三原色:紅Red,綠Green,藍Blue的通道,這三種色彩混合疊加,幾乎能形成人類視力所能感知的所有顏色。由此,設定圖片中每個畫素的RGB通道分量值,並根據特有的演算法或者濾波器,便可讓畫素呈現任何顏色。   圖2 光學三原色   2. 解析度 解析度是圖片在長和寬上各擁有的畫素,解析度越高,所包含的畫素就越多,圖片就越清晰。如圖3所示,是一張解析度為12*14的圖片,由橫向12個畫素點和縱向14個畫素點構成,共包含了12*14個畫素點。不難發現,由於解析度比較低,我們甚至無法辨別圖片的內容。   圖3 低解析度圖片
  如圖4所示,通過不斷增大圖片的解析度,不難看出,圖片的清晰度越來越高。   圖4 解析度的變化     二、馬賽克原理   增大圖片的解析度可以讓圖片變得更清晰,那麼我們是不是可以降低圖片的解析度來讓圖片變模糊?   馬賽克的原理就是降低原圖片的解析度。如圖5所示,首先我們將原圖分割成若干個大小一致的小方格,然後獲取每個小方格中的畫素點的平均色彩數值,最後使用獲取到的平均色彩數值替換該方格中所有的畫素點,即可實現圖片的馬賽克處理。   圖5 馬賽克原理   同時,我們還可以控制圖片中小方格的個數來實現馬賽克的強弱,如圖6所示。   圖6 馬賽克強弱控制
  三、馬賽克實現   相信大家已經熟悉了馬賽克的原理,下面我們將以全馬賽克圖片為例,為大家介紹基於ArkUI開發框架的馬賽克的具體實現。 1. 首先我們需獲取ArkUI開發框架的image能力,該能力提供了圖片開發的基本介面。  
import image from "@ohos.multimedia.image"
  2. 通過readPixelsToBuffer介面,一次性讀取圖片中所有的畫素點資料,每個畫素點資料都包含了RGB通道的分量值(如Red:18、Green:250、Blue:20)  
let bufferData = new ArrayBuffer(bitmap.getPixelBytesNumber());
await bitmap.readPixelsToBuffer(bufferData);
其中ArrayBuffer裡面快取的畫素點資料主要包括RGB通道的分量值及圖片透明度,參考程式碼如下:  
for (let index = 0; index < dataArray.length; index += 4) {
const r = dataArray[index];
const g = dataArray[index+1];
const b = dataArray[index+2];
const a = dataArray[index+3];
}

  

3. 根據自定義的單個小方格的Width和Height,將整個圖片分成若干小方格。  
//橫排的正方形個數
var x_index = Math.floor(targetWidth / realPixel_W);
//縱排的正方形個數
var y_index = Math.floor(targetHeight / realPixel_H);

  

4. 獲取每個小方格左上角的最大座標及右下角的最小座標,以確定小方格的區域。並根據每個小方格內的所有畫素點資料統一該區域的畫素,統一方式可以是取該區域內畫素點的平均值,或者隨機選取一個畫素。     參考程式碼如下:  
for (let ch = 0; ch < y_index; ch++) {
for (let cw = 0; cw < x_index; cw++) {
let max_x = (cw + 1) * realPixel_W > targetWidth ? targetWidth : (cw + 1) * realPixel_W;
let max_y = (ch + 1) * realPixel_H > targetHeight ? targetHeight : (ch + 1) * realPixel_H;
let min_x = cw * realPixel_W;
let min_y = ch * realPixel_H;
//取左上角的畫素值
let center_p = inPixels[min_y+1][min_x+1];
//設定該正方形裡的畫素統一
for (let zh = min_y; zh < max_y; zh++) {
for (let zw = min_x; zw < max_x; zw++) {
inPixels[zh][zw] = center_p;
}
}
}
}

  

5. 通過writeBufferToPixels介面,將統一的畫素點資料快取到ArrayBuffer中,並寫入PixelMap,由此得到整張馬賽克處理的圖片。  
writeBufferToPixels(src: ArrayBuffer): Promise<void>

 

四、塗鴉馬賽克   通過上文的介紹,相信大家已經基本掌握了馬賽克的實現。下面我們將為大家帶來馬賽克開發的具體例項“塗鴉馬賽克”,即可以根據手指滑動的軌跡,生成對應的馬賽克區域。本文僅提供實現思路及關鍵程式碼,感興趣的小夥伴可結合上文的介紹補全程式碼。   1. 給圖片新增Touch事件,獲取手指的運動軌跡。參考程式碼如下:  
Image(this._mCropPixelMap.pixelMap)
  .width(300)
  .height(300)
  .margin(10)
  .objectFit(ImageFit.Contain)
  .onTouch(event => {
    let array: TouchObject[] = event.changedTouches;
    for (let i = 0;i < array.length; i++) {
      //觸控的x y座標
      let centX = array[i].x;
      let centY = array[i].y;
    }
  });
  2. 根據運動軌跡,以觸控點的座標(x,y)為中心,根據自定義小方格的大小,動態確認馬賽克區域的位置。參考程式碼如下:  
//獲取到左上角的座標
let offMinX = Math.floor(centerX - pixel / 2);
let offMinY = Math.floor(centerY - pixel / 2);
//右下角的座標
let offMaxX = Math.floor(centerX + pixel / 2);
let offMaxY = Math.floor(centerY + pixel / 2);
offMinX = offMinX < 0 ? 0 : offMinX;
offMinY = offMinY < 0 ? 0 : offMinY;
offMaxX = offMaxX > targetWidth ? targetWidth : offMaxX;
offMaxY = offMaxY > targetHeight ? targetHeight : offMaxY;

  

3. 統一馬賽克區域的所有的畫素點值。  
//取左上角的畫素值
let center_p = PixelExampleUtils.inPixels[offMaxY+1][offMaxX+1];
//設定該正方形裡的畫素統一
for (let zh = offMinY; zh < offMaxY; zh++) {
  for (let zw = offMinX; zw < offMaxX; zw++) {
    PixelExampleUtils.inPixels[zh][zw] = center_p;
    changeArray[zh][zw] = center_p;
  }
}

  

4. 最後將更改的畫素點寫入圖片中,即可得到手指滑動軌跡的馬賽克圖片。   以上就是本期全部內容,恭喜你花幾分鐘時間獲得了一個實用的技能。期待廣大開發者能開發出更多有趣的馬賽克應用。