《图片拼接》一、ImageKit简介使用指南
HarmonyOS Image Kit 简介与实战指南从图片解码、编辑到编码的完整流程效果前言在HarmonyOS应用开发中图片处理是最常见的需求之一——从简单的图片展示到复杂的图片裁剪、拼接、滤镜、HDR合成等场景都离不开高效的图片处理工具支持。华为提供的Image Kit图片处理服务正是为此而生它封装了图片解码、像素级编辑、格式编码等核心能力支持JPEG、PNG、WebP、HEIF等主流格式是HarmonyOS图片开发的基石。本文将从核心概念入手逐步讲解Image Kit的三大核心模块——ImageSource解码、PixelMap编辑、ImagePacker编码并通过一个完整的图片处理示例带你快速上手。一、核心概念解析在动手编码之前需要先理解Image Kit中的三个核心对象它们构成了一条完整的图片处理流水线图片文件 → [ImageSource 解码] → [PixelMap 编辑] → [ImagePacker 编码] → 新图片文件1.1 ImageSource —— 图片解码入口ImageSource是图片解码的起点负责将各种格式的图片文件JPEG、PNG、WebP、GIF、BMP、HEIF等解码为内存中的位图数据。核心能力从文件路径、文件描述符、ArrayBuffer、URI等多种来源创建获取图片基本信息宽高、格式、密度等解码生成PixelMap对象创建方式import{image}fromkit.ImageKit;// 方式一从ArrayBuffer创建constimageSourceimage.createImageSource(buffer);// 方式二从文件路径创建constimageSourceimage.createImageSource(/path/to/image.jpg);// 方式三从文件描述符创建constimageSourceimage.createImageSource(file.fd);1.2 PixelMap —— 核心位图对象PixelMap是Image Kit中最重要的对象代表图片解码后的无压缩位图数据。所有的图片编辑操作都在PixelMap上进行。核心能力像素级读写readPixelsToBuffer/writePixels/readPixels图片变换旋转rotate、缩放scale、裁剪crop、镜像mirror透明度调整opacity获取图片信息getImageInfo关键属性操作方法说明读取全部像素readPixelsToBuffer(buffer)将整张图片的像素数据读入缓冲区写入指定区域writePixels(area)将缓冲区数据写入指定矩形区域获取总字节数getPixelBytesNumber()获取图像像素的总字节数获取每行字节数getBytesNumberPerRow()获取每行像素的字节数1.3 ImagePacker —— 图片编码输出ImagePacker负责将处理后的PixelMap重新编码为指定格式的图片文件是图片处理的最后一公里。支持格式JPEG、PNG、WebP、HEIF核心方法方法说明packToData(pixelMap, option)编码为ArrayBuffer返回编码后的二进制数据packToFile(pixelMap, file, option)直接编码并写入文件二、完整开发流程2.1 导入模块import{image}fromkit.ImageKit;import{fileIo}fromkit.CoreFileKit;2.2 图片解码从文件到PixelMap图片解码分为两步创建ImageSource→ 调用createPixelMap生成位图。asyncfunctiondecodeImage(uri:string):Promiseimage.PixelMap{// 1. 打开文件并读取到缓冲区constfilefileIo.openSync(uri,fileIo.OpenMode.READ_ONLY);constfileSizefileIo.statSync(file.fd).size;constbuffernewArrayBuffer(fileSize);fileIo.readSync(file.fd,buffer);fileIo.closeSync(file);// 2. 创建ImageSource并解码constimageSourceimage.createImageSource(buffer);// 可选设置解码参数目标尺寸、像素格式等constdecodingOpts:image.DecodingOptions{editable:true,// 必须设为true才能后续编辑像素desiredPixelFormat:image.PixelMapFormat.BGRA_8888,desiredSize:{width:500,height:800}// 可指定目标尺寸进行降采样};constpixelMapawaitimageSource.createPixelMap(decodingOpts);returnpixelMap;}要点说明editable: true是必须设置的否则无法对PixelMap进行像素级编辑desiredSize可用于降采样避免加载过大的原图导致内存问题BGRA_8888是推荐的像素格式每像素占4字节兼容性好2.3 图片编辑像素级操作PixelMap支持丰富的编辑操作以下演示几种常用场景场景一旋转和缩放// 顺时针旋转90度awaitpixelMap.rotate(90);// 缩放到原尺寸的50%awaitpixelMap.scale(0.5,0.5);// 裁剪指定区域awaitpixelMap.crop({x:0,y:0,size:{width:200,height:200}});场景二读取和写入像素数据图片拼接的核心// 读取整张图片的像素数据consttotalBytespixelMap.getPixelBytesNumber();constreadBuffernewArrayBuffer(totalBytes);pixelMap.readPixelsToBufferSync(readBuffer);// 将像素数据写入另一张图片的指定区域constwriteArea:image.PositionArea{pixels:readBuffer,// 像素数据缓冲区offset:0,// 缓冲区起始偏移stride:width*4,// 每行字节数 宽度 × 4(BGRA_8888)region:{size:{width:250,height:400},// 写入区域大小x:0,// 目标区域左上角X坐标y:0// 目标区域左上角Y坐标}};targetPixelMap.writePixelsSync(writeArea);场景三创建空白画布// 创建一个空白的PixelMap作为画布constcanvasWidth600;constcanvasHeight900;constcanvasBuffernewArrayBuffer(canvasWidth*canvasHeight*4);constinitOpts:image.InitializationOptions{alphaType:0,editable:true,pixelFormat:image.PixelMapFormat.BGRA_8888,size:{width:canvasWidth,height:canvasHeight}};constcanvasPixelMapimage.createPixelMapSync(canvasBuffer,initOpts);2.4 图片编码从PixelMap到文件处理完PixelMap后通常需要编码为JPEG/PNG格式保存或传输asyncfunctionencodePixelMap(pixelMap:image.PixelMap):PromiseArrayBuffer{constpackerimage.createImagePacker();constpackOpts:image.PackingOption{format:image/jpeg,// 支持 image/jpeg、image/png、image/webpquality:95// 质量参数0-100};// 编码为ArrayBufferconstencodedDataawaitpacker.packToData(pixelMap,packOpts);returnencodedData;}三、完整示例图片解码→缩放→编码下面是一个完整的示例展示如何从rawfile加载图片、解码、缩放后编码为新图片import{image}fromkit.ImageKit;import{resourceManager}fromkit.LocalizationKit;import{fileIo}fromkit.CoreFileKit;asyncfunctionprocessImage(context:Context):PromiseArrayBuffer{// 1. 从资源文件读取图片数据constresourceMgrcontext.resourceManager;constfileDataresourceMgr.getMediaContentSync($r(app.media.sample_photo));constsourceBufferfileData.buffer;// 2. 解码为PixelMapconstimageSourceimage.createImageSource(sourceBuffer);constdecodeOpts:image.DecodingOptions{editable:true,desiredPixelFormat:image.PixelMapFormat.BGRA_8888,desiredSize:{width:400,height:600}};constpixelMapawaitimageSource.createPixelMap(decodeOpts);// 3. 编辑操作旋转30度awaitpixelMap.rotate(30);// 4. 编码为JPEGconstpackerimage.createImagePacker();constpackOpts:image.PackingOption{format:image/jpeg,quality:90};constresultawaitpacker.packToData(pixelMap,packOpts);// 5. 释放资源awaitpixelMap.release();returnresult;}四、关键API速查表类别API说明创建ImageSourceimage.createImageSource(buffer)从ArrayBuffer创建创建ImageSourceimage.createImageSource(path)从文件路径创建解码imageSource.createPixelMap(opts)异步解码为PixelMap解码imageSource.createPixelMapSync(opts)同步解码为PixelMap创建画布image.createPixelMapSync(buffer, opts)从缓冲区直接创建PixelMap读取像素pixelMap.readPixelsToBufferSync(buffer)读取全部像素到缓冲区写入像素pixelMap.writePixelsSync(area)写入指定区域像素数据旋转pixelMap.rotate(angle)顺时针旋转指定角度缩放pixelMap.scale(x, y)按X/Y比例缩放裁剪pixelMap.crop(region)裁剪指定区域获取信息pixelMap.getImageInfo()获取图片宽高、格式等信息编码packer.packToData(pixelMap, opts)编码为ArrayBuffer编码packer.packToFile(pixelMap, file, opts)编码并直接写入文件释放pixelMap.release()释放PixelMap占用的内存五、最佳实践与注意事项5.1 内存管理及时释放PixelMap占用内存较大宽×高×4字节使用完毕后应调用release()释放降采样对于仅用于显示的场景通过desiredSize降采样可以大幅减少内存占用避免重复创建不要在build()方法中创建PixelMap应在aboutToAppear或事件回调中处理5.2 像素格式统一使用BGRA_8888格式进行像素读写确保readPixelsToBuffer和writePixels的格式一致如果需要RGBA格式使用RGBA_8888但注意字节序差异stride参数必须与像素格式匹配BGRA_8888每像素4字节stride 宽度 × 45.3 UI与图片处理分离禁止在build()方法中执行图片处理操作如createPixelMap、readPixelsToBuffer、writePixelsSync等build()方法应该只包含纯 UI 声明不应有任何副作用图片处理应放在事件回调如onClick或生命周期回调如aboutToAppear中在Builder函数中不能使用switch/case语句必须使用if/else if/else进行条件渲染5.4 编码格式选择格式适用场景特点JPEG照片、自然图像有损压缩文件小不支持透明PNGUI截图、带透明图片无损压缩支持透明文件较大WebP网络传输、通用兼具JPEG和PNG优点压缩率高六、总结Image Kit提供了一条完整的图片处理流水线ImageSource解码→ PixelMap编辑→ ImagePacker编码。掌握这三个核心对象的使用方法就能应对绝大多数图片处理需求ImageSource支持多种输入源是解码的起点PixelMap核心位图对象支持像素级读写和丰富的编辑操作ImagePacker将处理结果编码为指定格式支持质量控制在实际开发中建议将图片处理逻辑封装为独立的工具类与UI逻辑分离同时注意内存管理和资源释放确保应用的流畅运行。参考文档Image Kit简介图片解码图片绘制ArkTSohos.multimedia.image API参考图片解码图片绘制ArkTSohos.multimedia.image API参考