PixelMap是图像解码后的一种无压缩位图格式,图片解码是指将所支持格式的图片文件解码成统一的PixelMap格式,目前支持的图片格式有JPEG、PNG、GIF、WebP、BMP、SVG、ICO、DNG、HEIF。PixelMap主要用于图像显示或进一步处理。这种格式可以有效地存储图像的原始数据,使其可以方便地进行图像变换,如裁剪、缩放、偏移、旋转、翻转、设置透明度等。
使用HarmonyOS的PixelMap进行图像变换主要涉及以下几个步骤:
import { image } from '@kit.ImageKit'; import { common } from '@kit.AbilityKit'; @Entry @Component struct Index { @State imagePixelMap: PixelMap | undefined = undefined; @State scaleCount: number = 1; async aboutToAppear() { let pixelMap = this.getPixelMap(); this.imagePixelMap = pixelMap; } // 获取pixelMap getPixelMap() { let context = this.getUIContext().getHostContext() as common.UIAbilityContext; // 获取resourceManager资源管理 const resourceManager = context.resourceManager; // 获取图片数据 const fileData = resourceManager.getMediaContentSync($r('app.media.startIcon').id); // startIcon为测试图片,开发者需要替换为实际图片 const buffer = fileData.buffer; const imageSource = image.createImageSource(buffer); const pixelMap = imageSource.createPixelMapSync({ editable: true, desiredDynamicRange: image.DecodingDynamicRange.AUTO }); return pixelMap; } // 对pixelMap进行缩放 scalePixelMap(pixelMap: PixelMap, scaleCount: number) { pixelMap.scaleSync(scaleCount, scaleCount); return pixelMap; } build() { Column() { Image(this.imagePixelMap ? this.imagePixelMap : '') .width('80%') .height('60%') .objectFit(ImageFit.None) Row() { Button('缩小') .onClick(() => { if (this.imagePixelMap) { this.scaleCount = this.scaleCount - 0.1; // 获取图片基本信息,如果宽高大于300,继续缩小 let imageInfo = this.imagePixelMap.getImageInfoSync(); if (imageInfo.size.width > 300 || imageInfo.size.width > 300) { this.imagePixelMap = this.scalePixelMap(this.imagePixelMap, this.scaleCount); } } }) } } .width("100%") .height("100%") } }
更多图像变换示例效果。
Q:获取网络图片的PixelMap,如何进行居中剪裁(center crop)?
A:获取到PixelMap后,可调用crop(region: Region)方法,设置剪裁目标区域region参数为居中,对图片进行裁剪。
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的比例大小,缩放后编码的数据会变小,但是不一定成比例。
Q:使用PixelMap.rotate旋转图片没有改变。
A:这个问题涉及PixelMap的深拷贝,可以参考深拷贝demo。
Q:相同代码真机中无法正常旋转图片。
A:需要把图片解码设置选项DecodingOptions中设置editable:true。
Q:使用pixelMap.scale缩放图片没有效果。
A:pixelMap.scale是异步函数,需要在执行成功后再进行别的操作,否则图片没有缩放效果,需要使用同步接口pixelMap.scaleSync,或者在接口pixelMap.scale前增加异步await。
Q:如何对拍照后获取的JPEG图像进行裁剪,再写回文件?
A:先将JPEG图像解码获取PixelMap对象,对PixelMap使用crop接口进行裁剪,再将裁剪后的PixelMap编码成JPEG图像重新写入文件即可。
Q:为什么通过resourceManager.getMediaContent方法获取媒体文件内容后,通过createPixelMap方法转换失败?
A:image.createPixelMap方法的入参为图像像素数据,而resourceManager.getMediaContent方法回调函数中返回的是媒体文件内容数据,媒体文件数据可以直接用于播放,但是不能作为image.createPixelMap方法的入参,需要通过解码转换为可用图片像素数据才可以用于图片处理或渲染。