0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

图库四种常见操作的HarmonyOS图像编解码开发

鸿蒙系统HarmonyOS 来源:鸿蒙社区 作者:奶盖 2021-03-17 15:50 次阅读

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演示参考使用,产品化的代码需要考虑数据校验和国际化。

编辑:hfy

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • HarmonyOS
    +关注

    关注

    79

    文章

    1972

    浏览量

    30121
收藏 人收藏

    评论

    相关推荐

    图像传感器 图像压缩编解码技术

    图像传感器 图像压缩编解码技术 图像传感器在人们的文化、体育、生产、生活和科学研究中起到非常重要的作用。可以说,现代人类活动已经无法离开图像
    发表于 09-17 15:04

    四种图像噪声处理的MATLAB程序

    数模题目:图像去噪中几类稀疏变换的矩阵表示求帮助离散余弦变换,离散小波变换,主成分分析 和奇异值分解这四种的MATLAB编程程序
    发表于 05-15 18:34

    关于音频的PCM编解码几点疑问

    小弟最近在做2013年国赛题目红外通信装置,其实核心就是对音频信号进行PCM编解码,其中我们用到了MC14LC5480这款PCM编解码芯片,其中有几个疑问1.看全英文的文档介绍说有四种工作模式,但我
    发表于 03-15 11:30

    图片旋转 AnBetter Codelab记录帖

    功能介绍:HarmonyOS图像模块支持图像业务的开发常见功能如图像
    发表于 04-14 21:20

    HarmonyOS技术社区HDD期间Codelab活动获奖人名单公布

    HDD期间,HarmonyOS技术社区举办了2期的Codelab活动,主题分别有:第一期1、HarmonyOS JAVA通用组件(模块-Java 布局)2、基于图像模块实现图库图片的
    发表于 04-22 10:02

    基于HarmonyOS编解码能力,实现Camera实时预览流的播放

    1. 介绍视频编解码的主要工作:编码,即将原始的视频信息压缩为既定格式的数据。解码,即将已知格式的数据还原为视频信息。本教程将通过启动相机捕获预览帧,转换为视频原始数据并使用HarmonyOS视频
    发表于 09-17 10:56

    基于HarmonyOS图像编解码,实现图片的旋转、剪裁、缩放、镜像

    、缩放、镜像四种常见操作为例,给大家介绍HarmonyOS图像编解码的相关
    发表于 09-17 17:19

    二维码的四种主要应用模式

    本文介绍二维码主要的四种应用模式,包括读取数据模式、解码上网模式、解码验证模式、解码通信模式。
    发表于 01-25 11:52 3424次阅读

    编解码电路原理图

    编解码电路原理图都是值得参考的设计。
    发表于 05-11 17:33 28次下载

    基于FPGA的JPEG实时图像编解码系统

    基于FPGA的JPEG实时图像编解码系统
    发表于 08-29 16:05 15次下载

    常见四种触摸屏维修技巧

    本文主要介绍了常见四种触摸屏维修技巧以及触摸屏常见故障与处理方法。
    发表于 10-23 09:27 2.2w次阅读

    HarmonyOS开发文档(二)

    HarmonyOS 视频模块支持视频业务的开发和生态开放,开发者可以通过已开放的接口很容易地实现视频媒体的播放、操作和新功能开发。视频媒体的
    发表于 10-15 14:47 30次下载
    <b class='flag-5'>HarmonyOS</b><b class='flag-5'>开发</b>文档(二)

    四种常见图像滤波算法介绍

    作者丨一支程序媛@知乎 来源丨https://zhuanlan.zhihu.com/p/279602383 编辑丨极市平台 导读 图像滤波是一非常重要的图像处理技术,本文详细介绍了四种
    的头像 发表于 02-15 09:50 9987次阅读

    分享四种常见的MOS管栅极驱动电路

    分享四种常见的MOS管栅极驱动电路,都用过吗?
    的头像 发表于 10-26 10:06 5146次阅读

    走向实用的AI编解码阐述

    大家好,今天我分享的是走向实用的AI图像编解码。本次将着重从 “走向”两个字出发,阐述AI编解码研发的关键内容和进展。
    发表于 06-15 09:19 945次阅读
    走向实用的AI<b class='flag-5'>编解码</b>阐述