HarmonyOS 鸿蒙Next 加过水印后的图片内存较大问题

发布于 1周前 作者 zlyuanteng 最后一次编辑是 5天前 来自 鸿蒙OS

HarmonyOS 鸿蒙Next 加过水印后的图片内存较大问题

通过 canvas和OffScreenContext为图片添加水印,添加文字水印后的图片内存较大,如何在不修改原画质的技术上,降低添加水印后的图片大小。 这是我当前的代码: 添加水印:

/**
 * 获取图片信息,包含宽、高、类型
 * [@param](/user/param) params
 * [@returns](/user/returns)
 */
async function getImageInfo(params: GetImageInfoParams): Promise<ImageInfo> {
  const buffer = await this.getBuffer(params.src)
  console.log("vvvv: getImageInfo - buffer - ", buffer?.byteLength)
  let type: FileType = FileType.UNKNOWN
  if (buffer) {
    type = this.getFileTypeByBuffer(buffer)
  }

  const imageSource: image.ImageSource = image.createImageSource(buffer);
  const decodingOptions: image.DecodingOptions = {
    editable: true,
    desiredPixelFormat: 3,
  }
  const pixelMap: PixelMap = await imageSource.createPixelMap(decodingOptions)
  const info = await pixelMap.getImageInfo()
  const width = info.size.width
  const height = info.size.height
  return {
    width,
    height,
    type
  }
}

async function getPixelMap(url: string, imageInfo: ImageInfo): Promise<PixelMap> {
  const buffer = await this.getBuffer(url)
  console.log("vvvv: getPixelMap - buffer-", buffer?.byteLength)
  const imageSource: image.ImageSource = image.createImageSource(buffer);
  let opts: image.DecodingOptions = {
    editable: true,
    desiredSize: {
      height: imageInfo.height,
      width: imageInfo.width
    }
  };
  const pixelMap = await imageSource.createPixelMap(opts)
  return pixelMap
}

/**
 * 将buffer内容写入沙箱中
 * [@param](/user/param) buffer buffer内容
 * [@param](/user/param) name 文件名
 * [@param](/user/param) isTemporary 是否临时保存
 * [@returns](/user/returns)
 */
async function writeBufferToFile(buffer: ArrayBuffer, name: string, isTemporary: boolean = true) {
  const filesDir: string = isTemporary ? getContext(ImageCreator.mContext).tempDir : getContext(ImageCreator.mContext)
    .filesDir
  const foldPath = `${filesDir}/${ImageCreator.storePath}`
  if (!fs.accessSync(foldPath)) {
    fs.mkdirSync(foldPath)
  }
  let filePath = `${foldPath}/${name}`
  let file = fs.openSync(filePath, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE);
  fs.writeSync(file.fd, buffer);
  fs.fsyncSync(file.fd);
  fs.closeSync(file);
  return filePath
}

/**
 * 为图片添加水印
 * [@param](/user/param) sourcePath 图片地址
 */
async function imageWatermarkText(sourcePath) {
  const imageInfo: ImageInfo = await getImageInfo({ src: sourcePath })
  const imgWidth = imageInfo.width
  const imgHeight = imageInfo.height
  const type = imageInfo.type

  let textBaseline: CanvasTextBaseline = "middle";
  let textAlign: CanvasTextAlign = "center";
  let fillTextX: number = 0;
  let fillTextY: number = 0;

  const pixelMap = await getPixelMap(sourcePath, imageInfo)
  let offScreenCanvas = new OffscreenCanvas(imgWidth, imgHeight);
  let OffScreenContext = offScreenCanvas.getContext("2d");
  let imageScale = offScreenCanvas.width / display.getDefaultDisplaySync().width;
  OffScreenContext.drawImage(pixelMap, 0, 0, offScreenCanvas.width, offScreenCanvas.height);

  OffScreenContext.textAlign = "center";
  OffScreenContext.textBaseline = "middle";
  OffScreenContext.font = 28 * imageScale + "vp";
  OffScreenContext.fillStyle = "#ff0000";
  OffScreenContext.globalAlpha = 1;
  OffScreenContext.fillText("这是水印", 0, 0);

  // 获取加水印后图片ArrayBuffer,并存到内存种
  const newPixelMap = OffScreenContext.getPixelMap(0, 0, offScreenCanvas.width, offScreenCanvas.height)
  const imagePacker = image.createImagePacker();
  const imageBuffer = await imagePacker.packing(newPixelMap, {
    format: `image/${type}`,
    quality: 100
  });
  console.log("vvvv: imageBuffer-", imageBuffer.byteLength)
  // 存到内存中,并返回内存地址
  const fileName = `watermark_${Date.now()}.${type}`
  const filePath = await writeBufferToFile(imageBuffer, fileName)
  const LightResourcePath = ResourceProviderProxy.saveToCommonLightResourceFile(filePath, FILE_TYPE.IMAGE)
  const result: JSONObject = {
    tempFilePath: LightResourcePath
  }
}
 

原始图片的ArrayBuffer获取:

async function getBuffer(localFilePath: string): Promise<ArrayBuffer> {
  let srcFile = fs.openSync(localFilePath, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE);

const bufferSize = await this.getFileBufferSize(localFilePath) let arrayBuffer = new ArrayBuffer(bufferSize) const readLen = await fs.read(srcFile.fd, arrayBuffer) arrayBuffer = arrayBuffer.slice(0, readLen); this.saveBufferToAlbum(arrayBuffer) fs.closeSync(srcFile) return arrayBuffer }


更多关于HarmonyOS 鸿蒙Next 加过水印后的图片内存较大问题的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html

1 回复

更多关于HarmonyOS 鸿蒙Next 加过水印后的图片内存较大问题的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


针对HarmonyOS鸿蒙Next系统中加过水印后的图片内存较大的问题,这通常是由于水印处理过程中增加了图像数据的复杂度,导致图片文件大小增加。具体原因分析如下:

  1. 水印信息嵌入:水印的加入会改变原图像的像素信息,尤其当水印为彩色或包含半透明效果时,每个像素点的RGB或RGBA值都可能发生变化,导致整体数据量增加。

  2. 图像质量:为了保持水印的清晰度,可能会提升图像的分辨率或质量,这同样会增加图像的文件大小。

  3. 压缩算法:在加入水印后,如果选择的图像压缩算法不够高效,或者为了保持水印的可见性而减少压缩比,也会导致图片内存占用增大。

  4. 元数据:加入水印可能同时增加了图像的元数据,如版权信息、水印创建时间等,这些也会略微增加文件大小。

解决此问题的一种方法是优化水印处理算法,减少不必要的图像数据变化,同时选择合适的压缩算法和参数,以在保持水印可见性的同时减少文件大小。如果问题依旧没法解决请联系官网客服,官网地址是:https://www.itying.com/category-93-b0.html

回到顶部