色哟哟视频在线观看-色哟哟视频在线-色哟哟欧美15最新在线-色哟哟免费在线观看-国产l精品国产亚洲区在线观看-国产l精品国产亚洲区久久

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

HarmonyOS開(kāi)發(fā)案例:【圖片編輯】

jf_46214456 ? 來(lái)源:jf_46214456 ? 作者:jf_46214456 ? 2024-04-23 20:54 ? 次閱讀

介紹

是基于ArkTS的聲明式開(kāi)發(fā)范式的樣例,主要介紹了圖片編輯實(shí)現(xiàn)過(guò)程。樣例主要包含以下功能:

  1. 圖片的解碼。
  2. 使用PixelMap進(jìn)行圖片編輯,如裁剪、旋轉(zhuǎn)、亮度、透明度、飽和度等。
  3. 圖片的編碼。

相關(guān)概念

  • [圖片解碼]:讀取不同格式的圖片文件,無(wú)壓縮的解碼為位圖格式。
  • [PixelMap]:圖片解碼后的狀態(tài),用于對(duì)圖片像素進(jìn)行處理。
  • [圖片編碼]:圖片經(jīng)過(guò)像素處理完成之后,需要重新進(jìn)行編碼打包,生成需要的圖片格式。

環(huán)境搭建

軟件要求

  • [DevEco Studio]版本:DevEco Studio 3.1 Release。
  • OpenHarmony SDK版本:API version 9。

硬件要求

  • 開(kāi)發(fā)板類型:[潤(rùn)和RK3568開(kāi)發(fā)板]。
  • OpenHarmony系統(tǒng):3.2 Release。

環(huán)境搭建

完成本篇Codelab我們首先要完成開(kāi)發(fā)環(huán)境的搭建,本示例以RK3568開(kāi)發(fā)板為例,參照以下步驟進(jìn)行:

  1. [獲取OpenHarmony系統(tǒng)版本]:標(biāo)準(zhǔn)系統(tǒng)解決方案(二進(jìn)制)。以3.2 Release版本為例:
  2. 搭建燒錄環(huán)境。
    1. [完成DevEco Device Tool的安裝]
    2. [完成RK3568開(kāi)發(fā)板的燒錄](méi)
  3. 搭建開(kāi)發(fā)環(huán)境。
    1. 開(kāi)始前請(qǐng)參考[工具準(zhǔn)備],完成DevEco Studio的安裝和開(kāi)發(fā)環(huán)境配置。
    2. 開(kāi)發(fā)環(huán)境配置完成后,請(qǐng)參考[使用工程向?qū)創(chuàng)建工程(模板選擇“Empty Ability”)。
    3. 工程創(chuàng)建完成后,選擇使用[真機(jī)進(jìn)行調(diào)測(cè)]。
    4. HarmonyOS與OpenHarmony鴻蒙文檔籽料:mau123789是v直接拿

搜狗高速瀏覽器截圖20240326151450.png

代碼結(jié)構(gòu)解讀

本篇Codelab只對(duì)核心代碼進(jìn)行講解,對(duì)于完整代碼,我們會(huì)在gitee中提供。

├──entry/src/main/ets                            // 代碼區(qū)
│  ├──common                         
│  │  └──constant
│  │     └──CommonConstant.ets                   // 常量類
│  ├──entryability
│  │  └──EntryAbility.ts                         // 本地啟動(dòng)ability           
│  ├──pages
│  │  └──HomePage.ets                            // 本地主頁(yè)面    
│  ├──utils
│  │  ├──AdjustUtil.ets                          // 調(diào)節(jié)工具類
│  │  ├──CropUtil.ets                            // 裁剪工具類
│  │  ├──DecodeUtil.ets                          // 解碼工具類
│  │  ├──DrawingUtils.ets                        // Canvas畫圖工具類
│  │  ├──EncodeUtil.ets                          // 編碼工具類
│  │  ├──LoggerUtil.ets                          // 日志工具類
│  │  ├──MathUtils.ets                           // 坐標(biāo)轉(zhuǎn)換工具類
│  │  └──OpacityUtil.ets                         // 透明度調(diào)節(jié)工具類
│  ├──view
│  │  ├──AdjustContentView.ets                   // 色域調(diào)整視圖     
│  │  └──ImageSelect.ets                         // Canvas選擇框?qū)崿F(xiàn)類   
│  ├──viewmodel
│  │  ├──CropShow.ets                            // 選擇框顯示控制類
│  │  ├──CropType.ets                            // 按比例選取圖片
│  │  ├──IconListViewModel.ets                   // icon數(shù)據(jù)
│  │  ├──ImageEditCrop.ets                       // 圖片編輯操作類
│  │  ├──ImageFilterCrop.ets                     // 圖片操作收集類
│  │  ├──ImageSizeItem.ets                       // 圖片尺寸
│  │  ├──Line.ets                                // 線封裝類
│  │  ├──MessageItem.ets                         // 多線程封裝消息
│  │  ├──OptionViewModel.ets                     // 圖片處理封裝類
│  │  ├──PixelMapWrapper.ets                     // PixelMap封裝類
│  │  ├──Point.ets                               // 點(diǎn)封裝類
│  │  ├──Ratio.ets                               // 比例封裝類
│  │  ├──Rect.ets                                // 矩形封裝類
│  │  ├──RegionItem.ets                          // 區(qū)域封裝類
│  │  └──ScreenManager.ts                        // 屏幕尺寸計(jì)算工具類
│  └──workers
│     ├──AdjustBrightnessWork.ts                 // 亮度異步調(diào)節(jié)
│     └──AdjustSaturationWork.ts                 // 飽和度異步調(diào)節(jié)
└──entry/src/main/resources                      // 資源文件目錄

鴻蒙開(kāi)發(fā)指導(dǎo)文檔:[gitee.com/li-shizhen-skin/harmony-os/blob/master/README.md]

圖片解碼

在這個(gè)章節(jié)中,需要完成圖片解碼的操作,并將解碼后的圖片展示。效果如圖所示:

在進(jìn)行圖片編輯前需要先加載圖片,當(dāng)前文檔是在生命周期aboutToAppear開(kāi)始加載。具體實(shí)現(xiàn)步驟。

  1. 讀取資源文件。
  2. 將獲取的fd創(chuàng)建成圖片實(shí)例,通過(guò)實(shí)例獲取其pixelMap。
  3. 將解析好的pixelMap通過(guò)Image組件加載顯示。
// HomePage.ets
aboutToAppear() {
  this.pixelInit();
  ...
}

build() {
  Column() {
    ...
    Column() {
      if (this.isCrop && this.showCanvas && this.statusBar > 0) {
        if (this.isSaveFresh) {
          ImageSelect({
            statusBar: this.statusBar
          })
        }
        ...
      } else {
        if (this.isPixelMapChange) {
          Image(this.pixelMap)
            .scale({ x: this.imageScale, y: this.imageScale, z: 1 })
            .objectFit(ImageFit.None)
        }
        ...
      }
    }
    ...
  }
  ...
}

async getResourceFd(filename: string) {
  const resourceMgr = getContext(this).resourceManager;
  const context = getContext(this);
  if (filename === CommonConstants.RAW_FILE_NAME) {
    let imageBuffer = await resourceMgr.getMediaContent($r("app.media.ic_low"))
    let filePath = context.cacheDir + '/' + filename;
    let file = fs.openSync(filePath, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE);
    let writeLen = fs.writeSync(file.fd, imageBuffer.buffer);
    fs.copyFileSync(filePath, context.cacheDir + '/' + CommonConstants.RAW_FILE_NAME_TEST);
    return file.fd;
  } else {
    let filePath = context.cacheDir + '/' + filename;
    let file = fs.openSync(filePath, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE);
    return file.fd;
  }
}

async getPixelMap(fileName: string) {
  const fd = await this.getResourceFd(fileName);
  const imageSourceApi = image.createImageSource(fd);
  if (!imageSourceApi) {
    Logger.error(TAG, 'imageSourceAPI created failed!');
    return;
  }
  const pixelMap = await imageSourceApi.createPixelMap({
    editable: true
  });
  return pixelMap;
}

圖片處理

當(dāng)前章節(jié)需要完成圖片的裁剪、旋轉(zhuǎn)、色域調(diào)節(jié)(本章只介紹亮度、透明度、飽和度)等功能。

  • 裁剪:選取圖片中的部分進(jìn)行裁剪生成新的圖片。
  • 旋轉(zhuǎn):將圖片按照不同的角度進(jìn)行旋轉(zhuǎn),生成新的圖片。
  • 色域調(diào)節(jié):當(dāng)前Codelab色域調(diào)節(jié)的亮度、透明度和飽和度,使用色域模型RGB-HSV來(lái)實(shí)現(xiàn)的。
    • RGB:是我們接觸最多的顏色空間,分別為紅色(R),綠色(G)和藍(lán)色(B)。
    • HSV:是用色相H,飽和度S,明亮度V來(lái)描述顏色的變化。
      • H:色相H取值范圍為0°~360°,從紅色開(kāi)始按逆時(shí)針?lè)较蛴?jì)算,紅色為0°,綠色為120°,藍(lán)色為240°。
      • S:飽和度S越高,顏色則深而艷。光譜色的白光成分為0,飽和度達(dá)到最高。通常取值范圍為0%~100%,值越大,顏色越飽和。
      • V:明度V表示顏色明亮的程度,對(duì)于光源色,明度值與發(fā)光體的光亮度有關(guān);對(duì)于物體色,此值和物體的透射比或反射比有關(guān)。通常取值范圍為0%(黑)到100%(白)。
// AdjustUtil.ets
// rgb轉(zhuǎn)hsv
function rgb2hsv(red: number, green: number, blue: number) {
  let hsvH: number = 0, hsvS: number = 0, hsvV: number = 0;
  const rgbR: number = colorTransform(red);
  const rgbG: number = colorTransform(green);
  const rgbB: number = colorTransform(blue);
  const maxValue = Math.max(rgbR, Math.max(rgbG, rgbB));
  const minValue = Math.min(rgbR, Math.min(rgbG, rgbB));
  hsvV = maxValue * CommonConstants.CONVERT_INT;
  if (maxValue === 0) {
    hsvS = 0;
  } else {
    hsvS = Number((1 - minValue / maxValue).toFixed(CommonConstants.DECIMAL_TWO)) * CommonConstants.CONVERT_INT;
  }
  if (maxValue === minValue) {
    hsvH = 0;
  }
  if (maxValue === rgbR && rgbG >= rgbB) {
    hsvH = Math.floor(CommonConstants.ANGLE_60 * ((rgbG - rgbB) / (maxValue - minValue)));
  }
  if (maxValue === rgbR && rgbG < rgbB) {
    hsvH = Math.floor(CommonConstants.ANGLE_60 * ((rgbG - rgbB) / (maxValue - minValue)) + CommonConstants.ANGLE_360);
  }
  if (maxValue === rgbG) {
    hsvH = Math.floor(CommonConstants.ANGLE_60 * ((rgbB - rgbR) / (maxValue - minValue)) + CommonConstants.ANGLE_120);
  }
  if (maxValue === rgbB) {
    hsvH = Math.floor(CommonConstants.ANGLE_60 * ((rgbR - rgbG) / (maxValue - minValue)) + CommonConstants.ANGLE_240);
  }
  return [hsvH, hsvS, hsvV];
}
// hsv轉(zhuǎn)rgb
function hsv2rgb(hue: number, saturation: number, value: number) {
  let rgbR: number = 0, rgbG: number = 0, rgbB: number = 0;
  if (saturation === 0) {
    rgbR = rgbG = rgbB = Math.round((value * CommonConstants.COLOR_LEVEL_MAX) / CommonConstants.CONVERT_INT);
    return { rgbR, rgbG, rgbB };
  }
  const cxmC = (value * saturation) / (CommonConstants.CONVERT_INT * CommonConstants.CONVERT_INT);
  const cxmX = cxmC * (1 - Math.abs((hue / CommonConstants.ANGLE_60) % CommonConstants.MOD_2 - 1));
  const cxmM = (value - cxmC * CommonConstants.CONVERT_INT) / CommonConstants.CONVERT_INT;
  const hsvHRange = Math.floor(hue / CommonConstants.ANGLE_60);
  switch (hsvHRange) {
    case AngelRange.ANGEL_0_60:
      rgbR = (cxmC + cxmM) * CommonConstants.COLOR_LEVEL_MAX;
      rgbG = (cxmX + cxmM) * CommonConstants.COLOR_LEVEL_MAX;
      rgbB = (0 + cxmM) * CommonConstants.COLOR_LEVEL_MAX;
      break;
    case AngelRange.ANGEL_60_120:
      rgbR = (cxmX + cxmM) * CommonConstants.COLOR_LEVEL_MAX;
      rgbG = (cxmC + cxmM) * CommonConstants.COLOR_LEVEL_MAX;
      rgbB = (0 + cxmM) * CommonConstants.COLOR_LEVEL_MAX;
      break;
    case AngelRange.ANGEL_120_180:
      rgbR = (0 + cxmM) * CommonConstants.COLOR_LEVEL_MAX;
      rgbG = (cxmC + cxmM) * CommonConstants.COLOR_LEVEL_MAX;
      rgbB = (cxmX + cxmM) * CommonConstants.COLOR_LEVEL_MAX;
      break;
    case AngelRange.ANGEL_180_240:
      rgbR = (0 + cxmM) * CommonConstants.COLOR_LEVEL_MAX;
      rgbG = (cxmX + cxmM) * CommonConstants.COLOR_LEVEL_MAX;
      rgbB = (cxmC + cxmM) * CommonConstants.COLOR_LEVEL_MAX;
      break;
    case AngelRange.ANGEL_240_300:
      rgbR = (cxmX + cxmM) * CommonConstants.COLOR_LEVEL_MAX;
      rgbG = (0 + cxmM) * CommonConstants.COLOR_LEVEL_MAX;
      rgbB = (cxmC + cxmM) * CommonConstants.COLOR_LEVEL_MAX;
      break;
    case AngelRange.ANGEL_300_360:
      rgbR = (cxmC + cxmM) * CommonConstants.COLOR_LEVEL_MAX;
      rgbG = (0 + cxmM) * CommonConstants.COLOR_LEVEL_MAX;
      rgbB = (cxmX + cxmM) * CommonConstants.COLOR_LEVEL_MAX;
      break;
    default:
      break;
  }
  return [
    Math.round(rgbR),
    Math.round(rgbG),
    Math.round(rgbB)
  ];
}

圖片裁剪

  1. 通過(guò)pixelMap獲取圖片尺寸,為后續(xù)裁剪做準(zhǔn)備。
  2. 確定裁剪的方式,當(dāng)前裁剪默認(rèn)有自由選取、1:1選取、4:3選取、16:9選取。
  3. 通過(guò)pixelMap調(diào)用接口crop()進(jìn)行裁剪操作。

http://www.1cnz.cn/images/chaijie_default.png說(shuō)明: 當(dāng)前裁剪功能采用pixelMap裁剪能力直接做切割,會(huì)有疊加效果,后續(xù)會(huì)通過(guò)增加選取框?qū)Ξ?dāng)前功能進(jìn)行優(yōu)化。

// HomePage.ets
cropImage(index: CropType) {
  this.currentCropIndex = index;
  switch (this.currentCropIndex) {
    case CropType.ORIGINAL_IMAGE:
      this.cropRatio = CropRatioType.RATIO_TYPE_FREE;
      break;
    case CropType.SQUARE:
      this.cropRatio = CropRatioType.RATIO_TYPE_1_1;
      break;
    case CropType.BANNER:
      this.cropRatio = CropRatioType.RATIO_TYPE_4_3;
      break;
    case CropType.RECTANGLE:
      this.cropRatio = CropRatioType.RATIO_TYPE_16_9;
      break;
    default:
      this.cropRatio = CropRatioType.RATIO_TYPE_FREE;
      break;
  }
}

// ImageFilterCrop.ets
cropImage(pixelMap: PixelMapWrapper, realCropRect: RectF, callback: () = > void) {
  let offWidth = realCropRect.getWidth();
  let offHeight = realCropRect.getHeight();
  if (pixelMap.pixelMap!== undefined) {
    pixelMap.pixelMap.crop({
      size:{ height: vp2px(offHeight), width: vp2px(offWidth) },
      x: vp2px(realCropRect.left),
      y: vp2px(realCropRect.top)
    }, callback);
  }
}

圖片旋轉(zhuǎn)

  1. 確定旋轉(zhuǎn)方向,當(dāng)前支持順時(shí)針和逆時(shí)針旋轉(zhuǎn)。
  2. 通過(guò)pixelMap調(diào)用接口rotate()進(jìn)行旋轉(zhuǎn)操作。

// HomePage.ets
rotateImage(rotateType: RotateType) {
  if (rotateType === RotateType.CLOCKWISE) {
    try {
      if (this.pixelMap !== undefined) {
        this.pixelMap.rotate(CommonConstants.CLOCK_WISE)
          .then(() = > {
            this.flushPixelMapNew();
          })
      }
    } catch (error) {
      Logger.error(TAG, `there is a error in rotate process with ${error?.code}`);
    }
  }
  if (rotateType === RotateType.ANTI_CLOCK) {
    try {
      if (this.pixelMap !== undefined) {
        this.pixelMap.rotate(CommonConstants.ANTI_CLOCK)
          .then(() = > {
            this.flushPixelMapNew();
          })
      }
    } catch (error) {
      Logger.error(TAG, `there is a error in rotate process with ${error?.code}`);
    }
  }
}

亮度調(diào)節(jié)

  1. 將pixelMap轉(zhuǎn)換成ArrayBuffer。
  2. 將生成好的ArrayBuffer發(fā)送到worker線程。
  3. 對(duì)每一個(gè)像素點(diǎn)的亮度值按倍率計(jì)算。
  4. 將計(jì)算好的ArrayBuffer發(fā)送回主線程。
  5. 將ArrayBuffer寫入pixelMap,刷新UI。

http://www.1cnz.cn/images/chaijie_default.png說(shuō)明: 當(dāng)前亮度調(diào)節(jié)是在UI層面實(shí)現(xiàn)的,未實(shí)現(xiàn)細(xì)節(jié)優(yōu)化算法,只做簡(jiǎn)單示例。調(diào)節(jié)后的圖片會(huì)有色彩上的失真。

// AdjustContentView.ets
// 轉(zhuǎn)化成pixelMap及發(fā)送buffer到worker,返回?cái)?shù)據(jù)刷新ui
postToWorker(type: AdjustId, value: number, workerName: string) {
  let sliderValue = type === AdjustId.BRIGHTNESS ? this.brightnessLastSlider : this.saturationLastSlider;
  try {
    let workerInstance = new worker.ThreadWorker(workerName);
    const bufferArray = new ArrayBuffer(this.pixelMap.getPixelBytesNumber());
    this.pixelMap.readPixelsToBuffer(bufferArray).then(() = > {
      let message = new MessageItem(bufferArray, sliderValue, value);
      workerInstance.postMessage(message);
      if (this.postState) {
        this.deviceListDialogController.open();
      }
      this.postState = false;
      workerInstance.onmessage = (event: MessageEvents) = > {
        this.updatePixelMap(event)
      };
      if (type === AdjustId.BRIGHTNESS) {
        this.brightnessLastSlider = Math.round(value);
      } else {
        this.saturationLastSlider = Math.round(value);
      }
      workerInstance.onexit = () = > {
        if (workerInstance !== undefined) {
          workerInstance.terminate();
        }
      }
    });
  } catch (error) {
    Logger.error(`Create work instance fail, error message: ${JSON.stringify(error)}`)
  }
}

// AdjustBrightnessWork.ts
// worker線程處理部分
workerPort.onmessage = function(event : MessageEvents) {
  let bufferArray = event.data.buf;
  let last = event.data.last;
  let cur = event.data.cur;
  let buffer = adjustImageValue(bufferArray, last, cur);
  workerPort.postMessage(buffer);
  workerPort.close();
}

// AdjustUtil.ets
// 倍率計(jì)算部分
export function adjustImageValue(bufferArray: ArrayBuffer, last: number, cur: number) {
  return execColorInfo(bufferArray, last, cur, HSVIndex.VALUE);
}

透明度調(diào)節(jié)

  1. 獲取pixelMap。
  2. 調(diào)用接口opacity()進(jìn)行透明度調(diào)節(jié)。

// OpacityUtil.ets
export async function adjustOpacity(pixelMap: PixelMap, value: number) {
  if (!pixelMap) {
    return;
  }
  const newPixelMap = pixelMap;
  await newPixelMap.opacity(value / CommonConstants.SLIDER_MAX);
  return newPixelMap;
}

飽和度調(diào)節(jié)

  1. 將pixelMap轉(zhuǎn)換成ArrayBuffer。
  2. 將生成好的ArrayBuffer發(fā)送到worker線程。
  3. 對(duì)每一個(gè)像素點(diǎn)的飽和度按倍率計(jì)算。
  4. 將計(jì)算好的ArrayBuffer發(fā)送回主線程。
  5. 將ArrayBuffer寫入pixelMap,刷新UI。

http://www.1cnz.cn/images/chaijie_default.png說(shuō)明: 當(dāng)前飽和度調(diào)節(jié)是在UI層面實(shí)現(xiàn)的,未實(shí)現(xiàn)細(xì)節(jié)優(yōu)化算法,只做簡(jiǎn)單示例。調(diào)節(jié)后的圖片會(huì)有色彩上的失真。

// AdjustContentView.ets
// 轉(zhuǎn)化成pixelMap及發(fā)送buffer到worker,返回?cái)?shù)據(jù)刷新ui
postToWorker(type: AdjustId, value: number, workerName: string) {
  let sliderValue = type === AdjustId.BRIGHTNESS ? this.brightnessLastSlider : this.saturationLastSlider;
  try {
    let workerInstance = new worker.ThreadWorker(workerName);
    const bufferArray = new ArrayBuffer(this.pixelMap.getPixelBytesNumber());
    this.pixelMap.readPixelsToBuffer(bufferArray).then(() = > {
      let message = new MessageItem(bufferArray, sliderValue, value);
      workerInstance.postMessage(message);
      if (this.postState) {
        this.deviceListDialogController.open();
      }
      this.postState = false;
      workerInstance.onmessage = (event: MessageEvents) = > {
        this.updatePixelMap(event)
      };
      if (type === AdjustId.BRIGHTNESS) {
        this.brightnessLastSlider = Math.round(value);
      } else {
        this.saturationLastSlider = Math.round(value);
      }
      workerInstance.onexit = () = > {
        if (workerInstance !== undefined) {
          workerInstance.terminate();
        }
      }
    });
  } catch (error) {
    Logger.error(`Create work instance fail, error message: ${JSON.stringify(error)}`);
  }
}

// AdjustSaturationWork.ts
// worker線程處理部分
workerPort.onmessage = function(event : MessageEvents) {
  let bufferArray = event.data.buf;
  let last = event.data.last;
  let cur = event.data.cur;
  let buffer = adjustSaturation(bufferArray, last, cur)
  workerPort.postMessage(buffer);
  workerPort.close();
}

// AdjustUtil.ets
// 倍率計(jì)算部分
export function adjustSaturation(bufferArray: ArrayBuffer, last: number, cur: number) {
  return execColorInfo(bufferArray, last, cur, HSVIndex.SATURATION);
}

圖片編碼

圖片位圖經(jīng)過(guò)處理之后,還是屬于解碼的狀態(tài),還需要進(jìn)行打包編碼成對(duì)應(yīng)的格式,本章講解編碼的具體過(guò)程。

  1. 通過(guò)image組件創(chuàng)建打包工具packer。
  2. 使用PackingOption進(jìn)行打包參數(shù)設(shè)定,比如格式、壓縮質(zhì)量等。
  3. 打包成圖片信息數(shù)據(jù)imageData。
  4. 創(chuàng)建媒體庫(kù)media,獲取公共路徑。
  5. 創(chuàng)建媒體文件asset,獲取其fd。
  6. 使用fs將打包好的圖片數(shù)據(jù)寫入到媒體文件asset中。
// ImageSelect.ets
async encode(pixelMap: PixelMap | undefined) {
  if (pixelMap === undefined) {
    return;
  }

  const newPixelMap = pixelMap;
  // 打包圖片
  const imagePackerApi = image.createImagePacker();
  const packOptions: image.PackingOption = {
    format: CommonConstants.ENCODE_FORMAT,
    quality: CommonConstants.ENCODE_QUALITY
  }
  const imageData = await imagePackerApi.packing(newPixelMap, packOptions);
  Logger.info(TAG, `imageData's length is ${imageData.byteLength}`);
  // 獲取相冊(cè)路徑
  const context = getContext(this);
  const media = mediaLibrary.getMediaLibrary(context);
  const publicPath = await media.getPublicDirectory(mediaLibrary.DirectoryType.DIR_IMAGE);
  const currentTime = new Date().getTime();
  // 創(chuàng)建圖片資源
  const imageAssetInfo = await media.createAsset(
    mediaLibrary.MediaType.IMAGE,
    `${CommonConstants.IMAGE_PREFIX}_${currentTime}${CommonConstants.IMAGE_FORMAT}`,
    publicPath
  );
  const imageFd = await imageAssetInfo.open(CommonConstants.ENCODE_FILE_PERMISSION);
  await fs.write(imageFd, imageData);
  // 釋放資源
  await imageAssetInfo.close(imageFd);
  imagePackerApi.release();
  await media.release();
}

審核編輯 黃宇

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 鴻蒙
    +關(guān)注

    關(guān)注

    57

    文章

    2410

    瀏覽量

    43291
  • HarmonyOS
    +關(guān)注

    關(guān)注

    79

    文章

    1987

    瀏覽量

    31076
  • OpenHarmony
    +關(guān)注

    關(guān)注

    25

    文章

    3768

    瀏覽量

    17020
收藏 人收藏

    評(píng)論

    相關(guān)推薦

    TL3588-視頻開(kāi)發(fā)案

    TL3588-視頻開(kāi)發(fā)案
    的頭像 發(fā)表于 01-24 16:29 ?732次閱讀
    TL3588-視頻<b class='flag-5'>開(kāi)發(fā)案</b>例

    3568F-視頻開(kāi)發(fā)案

    3568F-視頻開(kāi)發(fā)案
    的頭像 發(fā)表于 04-12 13:51 ?966次閱讀
    3568F-視頻<b class='flag-5'>開(kāi)發(fā)案</b>例

    HarmonyOS開(kāi)發(fā)案例:【圖片編輯

    基于canvas組件、圖片編解碼,介紹了圖片編輯實(shí)現(xiàn)過(guò)程。
    的頭像 發(fā)表于 04-22 16:42 ?1035次閱讀
    <b class='flag-5'>HarmonyOS</b><b class='flag-5'>開(kāi)發(fā)案</b>例:【<b class='flag-5'>圖片</b><b class='flag-5'>編輯</b>】

    51單片機(jī)應(yīng)用開(kāi)發(fā)案例精選(代碼及圖片

    《51單片機(jī)應(yīng)用開(kāi)發(fā)案例精選》分為3部分。第1部分(第1章)講解單片機(jī)開(kāi)發(fā)的預(yù)備知識(shí),簡(jiǎn)要介紹了單片機(jī)的開(kāi)發(fā)流程、開(kāi)發(fā)工具和最小系統(tǒng);第2部分(第2章~第3章)講解單片機(jī)
    發(fā)表于 01-09 16:16

    HarmonyOS IoT 硬件開(kāi)發(fā)案例分享

    ``許思維老師HiSpark Wi-Fi IoT 開(kāi)發(fā)案例分享:案例一:AHT20溫濕度傳感器開(kāi)發(fā)、調(diào)試;案例二:oled屏驅(qū)動(dòng)庫(kù)移植,調(diào)試;案例三:用OLED屏播放視頻,Wi-Fi 和 TCP/IP 綜合應(yīng)用。 ``
    發(fā)表于 10-27 17:30

    HarmonyOS HiSpark Wi-Fi IoT套件】HarmonyOS IoT 硬件開(kāi)發(fā)案例分享

    HiSpark Wi-Fi IoT 開(kāi)發(fā)案例分享:案例一:AHT20溫濕度傳感器開(kāi)發(fā)、調(diào)試;案例二:oled屏驅(qū)動(dòng)庫(kù)移植,調(diào)試;案例三:用OLED屏播放視頻,Wi-Fi 和 TCP/IP 綜合應(yīng)用。
    發(fā)表于 10-27 19:12

    【潤(rùn)和直播課預(yù)告@華為開(kāi)發(fā)者學(xué)院】HarmonyOS設(shè)備開(kāi)發(fā)基礎(chǔ)課程|HiSpark WiFi-IoT 智能小車套件開(kāi)發(fā)案

    `【潤(rùn)和直播課預(yù)告@華為開(kāi)發(fā)者學(xué)院】HarmonyOS設(shè)備開(kāi)發(fā)基礎(chǔ)課程|HiSparkWiFi-IoT 智能小車套件開(kāi)發(fā)案例,3月18日(周四) 19:00-21:00,讓你的
    發(fā)表于 03-16 15:01

    HarmonyOS教程—基于圖片處理能力,實(shí)現(xiàn)一個(gè)圖片編輯模板

    :界面UI和圖片編輯器。模板界面UI部分主要為開(kāi)發(fā)者提供了:圖片編輯界面的設(shè)計(jì)參考,以及HarmonyO
    發(fā)表于 08-31 10:13

    51單片機(jī)應(yīng)用開(kāi)發(fā)案例精選-源代碼

    本內(nèi)容提供了51單片機(jī)應(yīng)用開(kāi)發(fā)案例精選-源代碼及開(kāi)發(fā)圖片
    發(fā)表于 08-10 09:40 ?538次下載
    51單片機(jī)應(yīng)用<b class='flag-5'>開(kāi)發(fā)案</b>例精選-源代碼

    許思維老師HarmonyOS IoT硬件開(kāi)發(fā)案例分享

    許思維老師HiSpark Wi-Fi IoT 開(kāi)發(fā)案例分享:案例一:AHT20溫濕度傳感器開(kāi)發(fā)、調(diào)試;案例二:oled屏驅(qū)動(dòng)庫(kù)移植,調(diào)試;案例三:用OLED屏播放視頻,Wi-Fi 和 TCP/IP 綜合應(yīng)用。
    發(fā)表于 10-29 10:39 ?39次下載
    許思維老師<b class='flag-5'>HarmonyOS</b> IoT硬件<b class='flag-5'>開(kāi)發(fā)案</b>例分享

    華為開(kāi)發(fā)HarmonyOS零基礎(chǔ)入門:Word圖片資源支持預(yù)覽效果

    華為開(kāi)發(fā)HarmonyOS零基礎(chǔ)入門:Word圖片資源支持預(yù)覽效果,list主鍵函數(shù)可以做布局,呈現(xiàn)多個(gè)堆疊顯示效果。
    的頭像 發(fā)表于 10-23 10:12 ?1586次閱讀
    華為<b class='flag-5'>開(kāi)發(fā)</b>者<b class='flag-5'>HarmonyOS</b>零基礎(chǔ)入門:Word<b class='flag-5'>圖片</b>資源支持預(yù)覽效果

    華為開(kāi)發(fā)者分論壇HarmonyOS學(xué)生公開(kāi)課-OpenHarmony Codelabs開(kāi)發(fā)案

    2021華為開(kāi)發(fā)者分論壇HarmonyOS學(xué)生公開(kāi)課-OpenHarmony Codelabs開(kāi)發(fā)案
    的頭像 發(fā)表于 10-24 11:25 ?2024次閱讀
    華為<b class='flag-5'>開(kāi)發(fā)</b>者分論壇<b class='flag-5'>HarmonyOS</b>學(xué)生公開(kāi)課-OpenHarmony Codelabs<b class='flag-5'>開(kāi)發(fā)案</b>例

    OpenHarmony上實(shí)現(xiàn)圖片編輯功能

    圖片編輯是在應(yīng)用中經(jīng)常用到的功能,比如相機(jī)拍完照片后可以對(duì)照片進(jìn)行編輯;截圖后可以對(duì)截圖進(jìn)行編輯;可以對(duì)圖庫(kù)中的圖片進(jìn)行
    的頭像 發(fā)表于 06-25 15:17 ?1370次閱讀
    OpenHarmony上實(shí)現(xiàn)<b class='flag-5'>圖片</b><b class='flag-5'>編輯</b>功能

    RK3568---NPU開(kāi)發(fā)案

    RK3568---NPU開(kāi)發(fā)案
    的頭像 發(fā)表于 01-19 13:50 ?1120次閱讀
    RK3568---NPU<b class='flag-5'>開(kāi)發(fā)案</b>例

    HarmonyOS開(kāi)發(fā)實(shí)例:【圖片編輯應(yīng)用】

    通過(guò)動(dòng)態(tài)設(shè)置元素樣式的方式,實(shí)現(xiàn)幾種常見(jiàn)的圖片操作,包括裁剪、旋轉(zhuǎn)、縮放和鏡像。
    的頭像 發(fā)表于 04-23 09:42 ?573次閱讀
    <b class='flag-5'>HarmonyOS</b><b class='flag-5'>開(kāi)發(fā)</b>實(shí)例:【<b class='flag-5'>圖片</b><b class='flag-5'>編輯</b>應(yīng)用】
    主站蜘蛛池模板: 国产高清在线a视频大全 | 亚洲精品久久久WWW游戏好玩 | 久久综合电影 | 粉嫩国产14xxxxx0000 | 亚洲欧美成人无码久久久 | 亚洲成人一区二区 | 国产午夜精品理论片久久影视 | 欧美 国产 日产 韩国 在线 | 伊人久久大香线蕉综合电影网 | 处88XXX| 欧美亚洲国内日韩自拍视频 | 亚洲视频在线观看免费 | 久久精品热在线观看85 | 国产精品一区二区在线观看 | 久久视频这里只精品6国产 久久视频在线视频观品15 | 狠狠色狠狠色综合日日2019 | 幼儿交1300部一区二区 | 牢记永久免费网址 | 99在线观看免费 | 成人在线精品视频 | 国产GV无码A片在线观看 | 國產日韓亞洲精品AV | 中国大陆一级毛片免费 | 午夜伦理电影在线观免费 | 国产午夜免费不卡精品理论片 | 开心久久激情 | 久久亚洲精品AV成人无 | 亚洲成色爱我久久 | 国产精品女上位在线观看 | 久久re6热在线视频 久久er国产免费精品 | 中文有码中文字幕免费视频 | 精品福利一区 | 亚洲欧洲日产国码中学 | 小夫妻天天恶战 | 久久中文字幕综合不卡一二区 | 国产最新地址 | 国产亚洲精品久久播放 | 国产精品禁18久久久夂久 | 亚洲国产成人爱AV在线播放丿 | 欧美日韩中文国产一区 | 日韩久久影院 |