HarmonyOS鸿蒙Next中如何将一张图片拆分成n*n的矩形图片

HarmonyOS鸿蒙Next中如何将一张图片拆分成nn的矩形图片 如何将一张图片拆分成nn的矩形图片,n>100

5 回复

【背景知识】

PixelMap是图像解码后的一种无压缩位图格式,主要用于图像显示或进一步处理。这种格式可以有效地存储图像的原始数据,使其可以方便地进行图像变换,如裁剪、缩放、偏移、旋转、翻转、设置透明度等。

【解决方案】

使用HarmonyOS的PixelMap进行图像变换主要涉及以下几个步骤:

  1. 图片解码:首先,需要加载并解码图片文件,这将返回一个PixelMap对象,该对象用于后续的图像操作。
  2. 获取图片信息:在进行变换之前,需要获取图片的一些基本信息,如宽度和高度。可以通过调用getImageInfo()方法来获取这些信息。
// 获取图片大小
pixelMap.getImageInfo().then(info => {
    console.info('info.width = ' + info.size.width);
    console.info('info.height = ' + info.size.height);
}).catch(err => {
    console.error("Failed to obtain the image pixel map information. And the error is: " + err);
});
  1. 执行图像变换:包括裁剪、缩放、旋转、翻转、透明度修改等操作。这些操作通常通过PixelMap提供的方法来实现。
@Entry
@Component
struct Index {
  @State imagePixelMap: PixelMap | undefined = undefined
  @State edit: boolean = false
  aboutToAppear(): void {
  }
  @Builder
  buttonModel($$: GeneratedTypeLiteralInterface_1) {
    Button($$.textContent)
      .fontSize(14)
      .height(30)
      .width(60)
      .borderRadius(10)
      .backgroundColor('#E8A027')
      .onClick(() => {
        $$.action
        this.edit = true
      })
  }
  async get_pixelmap() {
    const context = getContext(this)
    const resourceMgr = context.resourceManager
    const fileData = await resourceMgr.getMediaContent($r('app.media.testImg'))
    const buffer = fileData.buffer
    const imageSource = image.createImageSource(buffer)
    const pixelMap = await imageSource.createPixelMap()
    return pixelMap
  }
  // 对pixelMap进行裁剪
  async crop_image() {
    let pixelMap = await this.get_pixelmap()
    pixelMap.crop({ x: 0, y: 0, size: { height: 300, width: 300 } })
    this.imagePixelMap = pixelMap
  }
  // 对pixelMap进行缩放
  async scale_image() {
    let pixelMap = await this.get_pixelmap()
    pixelMap.scale(0.5, 0.5)
    this.imagePixelMap = pixelMap
  }
  // 对pixelMap进行偏移
  async translate_image() {
    let pixelMap = await this.get_pixelmap()
    pixelMap.translate(100, 100);
    this.imagePixelMap = pixelMap
  }
  // 对pixelMap进行旋转
  async rotate_image() {
    let pixelMap = await this.get_pixelmap()
    pixelMap.rotate(90);
    this.imagePixelMap = pixelMap
  }
  // 对pixelMap进行翻转
  // 垂直翻转
  async flip_image() {
    let pixelMap = await this.get_pixelmap()
    pixelMap.flip(false, true);
    this.imagePixelMap = pixelMap
  }
  // 对pixelMap进行透明度调整
  async opacity_image() {
    let pixelMap = await this.get_pixelmap()
    pixelMap.opacity(0.5);
    this.imagePixelMap = pixelMap
  }
}

【常见FAQ】

Q:获取网络图片的PixelMap,如何进行center crop? A:获取到PixelMap后,可调用crop方法,根据输入的尺寸对图片进行裁剪。

async function Crop() {
  let region: image.Region = { x: 0, y: 0, size: { height: 100, width: 100 } };
  if (pixelMap != undefined) {
    pixelMap.crop(region, (err: BusinessError) => {
      if (err) {
        console.error(`Failed to crop pixelmap. code is ${err.code}, message is ${err.message}`);
        return;
      } else {
        console.info("Succeeded in cropping pixelmap.");
      }
    })
  }
}

Q:HarmonyOS系统上,有时候竖屏图片加载时会显示成横屏。 A:有些设备会给图片加一个旋转属性,HarmonyOS相册组件是Image的api无法读取此属性,想要规避这个问题可以通过getImageProperty获取旋转信息,判断图片是否要旋转,如果需要旋转可以通过.rotate(90)进行调整。

Q:图片缩放算法函数scaleSync(x: number, y: number),x和y大概0.2左右(图片长宽尺寸缩小0.046),最终图片byte值为原始图的0.0558倍,这个结果不符合预期,预期也是0.046倍。 A:scaleSync影响的是pixelmap的比例大小,缩放后编码的数据会变小,但是不一定成比列。

更多关于HarmonyOS鸿蒙Next中如何将一张图片拆分成n*n的矩形图片的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


试试这个图片裁剪第三方库,可以自定义设置裁剪宽高(你也可以设置成n*n)。裁剪完后会给你返回裁剪后的uri。

OpenHarmony三方库中心仓

在HarmonyOS鸿蒙Next中,可以使用ImageCanvas组件来实现图片的拆分。首先,加载图片到Image组件,然后通过CanvasdrawImage方法,按照指定的n*n尺寸进行裁剪。使用CanvasRenderingContext2DgetImageDataputImageData方法获取和绘制每个小矩形图片。最后,将每个小图片保存或显示。

在HarmonyOS Next中,可以使用图像处理API实现图片分割。以下是关键实现步骤:

  1. 使用Image组件加载原图:
let image = new Image();
image.src = 'path/to/image.jpg';
  1. 获取图片尺寸后计算分割参数:
let width = image.width;
let height = image.height;
let tileSize = Math.min(width, height) / n;  // 计算每个小方块尺寸
  1. 使用Canvas进行分割处理:
let canvas = new Canvas();
let ctx = canvas.getContext('2d');

for(let i=0; i<n; i++) {
    for(let j=0; j<n; j++) {
        // 绘制每个小方块
        ctx.drawImage(image, 
            i*tileSize, j*tileSize, tileSize, tileSize,
            0, 0, tileSize, tileSize);
        
        // 获取分割后的图片数据
        let tileData = canvas.toDataURL();
        // 保存或处理tileData...
    }
}
  1. 性能优化建议:
  • 对于n>100的情况,建议使用Worker线程处理
  • 可考虑分批次处理避免内存问题
  • 大图处理时注意OOM问题

注意:实际实现时需根据具体场景调整参数,特别是处理大图和大量分割时要注意性能问题。

回到顶部