1. 项目介绍
harmonyos图像模块支持图像业务的开发,常见功能如图像解码、图像编码、基本的位图操作、图像编辑等。当然,也支持通过接口组合来实现更复杂的图像处理逻辑。本教程以图库图片中旋转、剪裁、缩放、镜像四种常见操作为例,给大家介绍harmonyos图像编解码的相关开发指导。
2. 将图片转换为pixelmap
图像解码就是将所支持格式的存档图片解码成统一的pixelmap图像,用于后续图像显示或其他处理,比如旋转、缩放、剪裁等。当前支持格式包括jpeg、png、gif、heif、webp、bmp。本例为您提供了getpixelmapfromresource函数,可以将resources/base/media目录下的图片资源转换为pixelmap图像,其中入参为图片的资源id。
private pixelmap getpixelmapfromresource(int resourceid) {
inputstream inputstream = null; try { // 创建图像数据源imagesource对象 inputstream = getcontext().getresourcemanager().getresource(resourceid); imagesource.sourceoptions srcopts = new imagesource.sourceoptions(); srcopts.formathint = image/jpg; imagesource imagesource = imagesource.create(inputstream, srcopts); // 设置图片参数 imagesource.decodingoptions decodingoptions = new imagesource.decodingoptions(); return imagesource.createpixelmap(decodingoptions); } catch (ioexception e) { hilog.info(label_log, ioexception); } catch (notexistexception e) { hilog.info(label_log, notexistexception); } finally { if (inputstream != null) { try { inputstream.close(); } catch (ioexception e) { hilog.info(label_log, inputstream ioexception); } } } return null;}
3. 图片参数设置
本例使用图片像素的尺寸为1024*768,点击一次旋转按钮会进行90度的旋转,缩放是按照2:1的比例进行缩放,剪裁是保证宽度不变的情况下对高度进行400像素的剪裁,相关参数设置如下所示:
// 设置图片参数 imagesource.decodingoptions decodingoptions = new imagesource.decodingoptions(); // 旋转 decodingoptions.rotatedegrees = 90 * whirlcount; // 缩放 decodingoptions.desiredsize = new size(isscale ? 512 : 0, isscale ? 384 : 0); // 剪裁 decodingoptions.desiredregion = new rect(0, 0, iscorp ? 1024 : 0, iscorp ? 400 : 0); 4. 图片镜像操作
图片镜像操作就是对图片以纵坐标为轴制作对称图片。image绘制的时候会调用ondraw方法,本例采用对图像canvas画布的镜像操作实现图片的镜像显示,示例代码如下所示:
private void mirrorimage(pixelmap pixelmap) { scalex = -scalex; image.adddrawtask( new component.drawtask() { @override public void ondraw(component component, canvas canvas) { if (ismirror) { ismirror = false; pixelmapholder pmh = new pixelmapholder(pixelmap); canvas.scale( scalex, 1.0f, (float) pixelmap.getimageinfo().size.width / 2, (float) pixelmap.getimageinfo().size.height / 2); canvas.drawpixelmapholder( pmh, 0, 0, new paint()); } } }); } 5. 完整示例
以手机为例,初始化页面如图1所示,依次点击按钮可以实现图片的旋转、剪裁、缩放、镜像,效果如下所示(您需要准备一张像素尺寸为1024*768的图片,放到imagedemo\entry\src\main\resources\base\media目录下):
示例代码如下:
import com.huawei.codelab.resourcetable; import ohos.aafwk.ability.abilityslice; import ohos.aafwk.content.intent; import ohos.agp.components.button; import ohos.agp.components.component; import ohos.agp.components.image; import ohos.agp.render.canvas; import ohos.agp.render.paint; import ohos.agp.render.pixelmapholder; import ohos.global.resource.notexistexception; import ohos.hiviewdfx.hilog; import ohos.hiviewdfx.hiloglabel; import ohos.media.image.imagesource; import ohos.media.image.pixelmap; import ohos.media.image.common.pixelformat; import ohos.media.image.common.rect; import ohos.media.image.common.size; import java.io.ioexception; import java.io.inputstream; /** * 图像主页面 */ public class mainabilityslice extends abilityslice { private static final hiloglabel label_log = new hiloglabel(3, 0xd001100, mainabilityslice); image image; pixelmap imagepixelmap; button whirlimagebtn; button cropimagebtn; button scaleimagebtn; button mirrorimagebtn; private int whirlcount = 0; private boolean iscorp = false; private boolean isscale = false; private boolean ismirror = false; private float scalex = 1.0f; @override public void onstart(intent intent) { super.onstart(intent); super.setuicontent(resourcetable.layout_ability_main); initview(); } private void initview() { if (findcomponentbyid(resourcetable.id_whirl_image) instanceof button) { whirlimagebtn = (button) findcomponentbyid(resourcetable.id_whirl_image); } if (findcomponentbyid(resourcetable.id_crop_image) instanceof button) { cropimagebtn = (button) findcomponentbyid(resourcetable.id_crop_image); } if (findcomponentbyid(resourcetable.id_scale_image) instanceof button) { scaleimagebtn = (button) findcomponentbyid(resourcetable.id_scale_image); } if (findcomponentbyid(resourcetable.id_mirror_image) instanceof button) { mirrorimagebtn = (button) findcomponentbyid(resourcetable.id_mirror_image); } if (findcomponentbyid(resourcetable.id_image) instanceof image) { image = (image) findcomponentbyid(resourcetable.id_image); } whirlimagebtn.setclickedlistener(new buttonclick()); cropimagebtn.setclickedlistener(new buttonclick()); scaleimagebtn.setclickedlistener(new buttonclick()); mirrorimagebtn.setclickedlistener(new buttonclick()); } private class buttonclick implements component.clickedlistener { @override public void onclick(component component) { int btnid = component.getid(); switch (btnid) { case resourcetable.id_whirl_image: // 旋转图片 whirlcount++; iscorp = false; isscale = false; ismirror = false; imagepixelmap = getpixelmapfromresource(resourcetable.media_shanghai); image.setpixelmap(imagepixelmap); break; case resourcetable.id_crop_image: // 剪裁图片 whirlcount = 0; iscorp = !iscorp; isscale = false; ismirror = false; imagepixelmap = getpixelmapfromresource(resourcetable.media_shanghai); image.setpixelmap(imagepixelmap); break; case resourcetable.id_scale_image: // 缩放图片 whirlcount = 0; iscorp = false; isscale = !isscale; ismirror = false; imagepixelmap = getpixelmapfromresource(resourcetable.media_shanghai); image.setpixelmap(imagepixelmap); break; case resourcetable.id_mirror_image: // 镜像图片 whirlcount = 0; iscorp = false; isscale = false; ismirror = true; imagepixelmap = getpixelmapfromresource(resourcetable.media_shanghai); mirrorimage(imagepixelmap); image.setpixelmap(imagepixelmap); break; default: break; } } } private void mirrorimage(pixelmap pixelmap) { scalex = -scalex; image.adddrawtask( new component.drawtask() { @override public void ondraw(component component, canvas canvas) { if (ismirror) { ismirror = false; pixelmapholder pmh = new pixelmapholder(pixelmap); canvas.scale( scalex, 1.0f, (float) pixelmap.getimageinfo().size.width / 2, (float) pixelmap.getimageinfo().size.height / 2); canvas.drawpixelmapholder( pmh, 0, 0, new paint()); } } }); } /** * 通过图片id返回pixelmap * * @param resourceid 图片的资源id * @return 图片的pixelmap */ private pixelmap getpixelmapfromresource(int resourceid) { inputstream inputstream = null; try { // 创建图像数据源imagesource对象 inputstream = getcontext().getresourcemanager().getresource(resourceid); imagesource.sourceoptions srcopts = new imagesource.sourceoptions(); srcopts.formathint = image/jpg; imagesource imagesource = imagesource.create(inputstream, srcopts); // 设置图片参数 imagesource.decodingoptions decodingoptions = new imagesource.decodingoptions(); // 旋转 decodingoptions.rotatedegrees = 90 * whirlcount; // 缩放 decodingoptions.desiredsize = new size(isscale ? 512 : 0, isscale ? 384 : 0); // 剪裁 decodingoptions.desiredregion = new rect(0, 0, iscorp ? 1024 : 0, iscorp ? 400 : 0); decodingoptions.desiredpixelformat = pixelformat.argb_8888; return imagesource.createpixelmap(decodingoptions); } catch (ioexception e) { hilog.info(label_log, ioexception); } catch (notexistexception e) { hilog.info(label_log, notexistexception); } finally { if (inputstream != null) { try { inputstream.close(); } catch (ioexception e) { hilog.info(label_log, inputstream ioexception); } } } return null; } @override public void onactive() { super.onactive(); } @override public void onforeground(intent intent) { super.onforeground(intent); } } 布局代码如下:
此外您还需在resource/base/graphic目录下添加background_button.xml
说明
以上代码仅demo演示参考使用,产品化的代码需要考虑数据校验和国际化。
人大金仓&恒生电子助力湘财证券TA系统国产化升级
以“科技向善”引领AI全方位治理,确保AI“可知”“可控”“可用”“可靠”
搭载高通骁龙855芯片和5G,高通VR原型机亮相CES
DS18B20数字温度传感器的源代码
符合功能安全要求的动态测试工具-TESSY
图库四种常见操作的HarmonyOS图像编解码开发
理想三大核心风险,李想曝光!
全球机器人消费市场高度集中,新加坡和韩国装机密度领先全球
“新四化”推动汽车存储需求,西部数据引领车载存储革新
基于MAXREFDES220的心率和 SpO2 血氧传感器的医疗监测电路设计
如何用FPGA结合音频编解码芯片
MOSFET的阈值、ID-VGS特性及温度特性
2022高工储能年会观察:用户侧储能“突飞猛进”
小米MIUI9发布时间曝光:官方今日下午公布小米MIUI9发布时间
使用新型单芯片双ADC前端改进数据采集
TI助力工程师进行工业系统创新
德勤调查:美国67%消费者准备更换5G手机
软件安全构建成熟度模型BSIMM9 现已上线
如何设计一款好的电源产品?
减压阀的设置要求