0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

圖庫四種常見操作的HarmonyOS圖像編解碼開發(fā)

鴻蒙系統(tǒng)HarmonyOS ? 來源:鴻蒙社區(qū) ? 作者:奶蓋 ? 2021-03-17 15:50 ? 次閱讀

1. 項目介紹

HarmonyOS圖像模塊支持圖像業(yè)務(wù)的開發(fā),常見功能如圖像解碼、圖像編碼、基本的位圖操作、圖像編輯等。當然,也支持通過接口組合來實現(xiàn)更復(fù)雜的圖像處理邏輯。本教程以圖庫圖片中旋轉(zhuǎn)、剪裁、縮放、鏡像四種常見操作為例,給大家介紹HarmonyOS圖像編解碼的相關(guān)開發(fā)指導(dǎo)。

2. 將圖片轉(zhuǎn)換為PixelMap

圖像解碼就是將所支持格式的存檔圖片解碼成統(tǒng)一的PixelMap圖像,用于后續(xù)圖像顯示或其他處理,比如旋轉(zhuǎn)、縮放、剪裁等。當前支持格式包括JPEG、PNG、GIF、HEIF、WebP、BMP。本例為您提供了getPixelMapFromResource函數(shù),可以將resources/base/media目錄下的圖片資源轉(zhuǎn)換為PixelMap圖像,其中入?yún)閳D片的資源ID。

private PixelMap getPixelMapFromResource(int resourceId) {

    InputStream inputStream = null;
    try {
        // 創(chuàng)建圖像數(shù)據(jù)源ImageSource對象
        inputStream = getContext().getResourceManager().getResource(resourceId);
        ImageSource.SourceOptions srcOpts = new ImageSource.SourceOptions();
        srcOpts.formatHint = "image/jpg";
        ImageSource imageSource = ImageSource.create(inputStream, srcOpts);


        // 設(shè)置圖片參數(shù)
        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. 圖片參數(shù)設(shè)置

本例使用圖片像素的尺寸為1024*768,點擊一次旋轉(zhuǎn)按鈕會進行90度的旋轉(zhuǎn),縮放是按照2:1的比例進行縮放,剪裁是保證寬度不變的情況下對高度進行400像素的剪裁,相關(guān)參數(shù)設(shè)置如下所示:

// 設(shè)置圖片參數(shù) 
ImageSource.DecodingOptions decodingOptions = new ImageSource.DecodingOptions(); 
// 旋轉(zhuǎn) 
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繪制的時候會調(diào)用onDraw方法,本例采用對圖像Canvas畫布的鏡像操作實現(xiàn)圖片的鏡像顯示,示例代碼如下所示:

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所示,依次點擊按鈕可以實現(xiàn)圖片的旋轉(zhuǎn)、剪裁、縮放、鏡像,效果如下所示(您需要準備一張像素尺寸為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: 
                    // 旋轉(zhuǎn)圖片 
                    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 { 
            // 創(chuàng)建圖像數(shù)據(jù)源ImageSource對象 
            inputStream = getContext().getResourceManager().getResource(resourceId); 
            ImageSource.SourceOptions srcOpts = new ImageSource.SourceOptions(); 
            srcOpts.formatHint = "image/jpg"; 
            ImageSource imageSource = ImageSource.create(inputStream, srcOpts); 
 
            // 設(shè)置圖片參數(shù) 
            ImageSource.DecodingOptions decodingOptions = new ImageSource.DecodingOptions(); 
            // 旋轉(zhuǎn) 
            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演示參考使用,產(chǎn)品化的代碼需要考慮數(shù)據(jù)校驗和國際化。

編輯:hfy

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • HarmonyOS
    +關(guān)注

    關(guān)注

    79

    文章

    1975

    瀏覽量

    30201
收藏 人收藏

    評論

    相關(guān)推薦

    圖像傳感器 圖像壓縮編解碼技術(shù)

    圖像傳感器 圖像壓縮編解碼技術(shù) 圖像傳感器在人們的文化、體育、生產(chǎn)、生活和科學(xué)研究中起到非常重要的作用??梢哉f,現(xiàn)代人類活動已經(jīng)無法離開圖像
    發(fā)表于 09-17 15:04

    四種圖像噪聲處理的MATLAB程序

    數(shù)模題目:圖像去噪中幾類稀疏變換的矩陣表示求幫助離散余弦變換,離散小波變換,主成分分析 和奇異值分解這四種的MATLAB編程程序
    發(fā)表于 05-15 18:34

    關(guān)于音頻的PCM編解碼幾點疑問

    小弟最近在做2013年國賽題目紅外通信裝置,其實核心就是對音頻信號進行PCM編解碼,其中我們用到了MC14LC5480這款PCM編解碼芯片,其中有幾個疑問1.看全英文的文檔介紹說有四種工作模式,但我
    發(fā)表于 03-15 11:30

    圖片旋轉(zhuǎn) AnBetter Codelab記錄帖

    功能介紹:HarmonyOS圖像模塊支持圖像業(yè)務(wù)的開發(fā)常見功能如圖像
    發(fā)表于 04-14 21:20

    HarmonyOS技術(shù)社區(qū)HDD期間Codelab活動獲獎人名單公布

    HDD期間,HarmonyOS技術(shù)社區(qū)舉辦了2期的Codelab活動,主題分別有:第一期1、HarmonyOS JAVA通用組件(模塊-Java 布局)2、基于圖像模塊實現(xiàn)圖庫圖片的
    發(fā)表于 04-22 10:02

    基于HarmonyOS編解碼能力,實現(xiàn)Camera實時預(yù)覽流的播放

    1. 介紹視頻編解碼的主要工作:編碼,即將原始的視頻信息壓縮為既定格式的數(shù)據(jù)。解碼,即將已知格式的數(shù)據(jù)還原為視頻信息。本教程將通過啟動相機捕獲預(yù)覽幀,轉(zhuǎn)換為視頻原始數(shù)據(jù)并使用HarmonyOS視頻
    發(fā)表于 09-17 10:56

    基于HarmonyOS圖像編解碼,實現(xiàn)圖片的旋轉(zhuǎn)、剪裁、縮放、鏡像

    、縮放、鏡像四種常見操作為例,給大家介紹HarmonyOS圖像編解碼的相關(guān)
    發(fā)表于 09-17 17:19

    二維碼的四種主要應(yīng)用模式

    本文介紹二維碼主要的四種應(yīng)用模式,包括讀取數(shù)據(jù)模式、解碼上網(wǎng)模式、解碼驗證模式、解碼通信模式。
    發(fā)表于 01-25 11:52 ?3429次閱讀

    編解碼電路原理圖

    編解碼電路原理圖都是值得參考的設(shè)計。
    發(fā)表于 05-11 17:33 ?28次下載

    基于FPGA的JPEG實時圖像編解碼系統(tǒng)

    基于FPGA的JPEG實時圖像編解碼系統(tǒng)
    發(fā)表于 08-29 16:05 ?15次下載

    常見四種觸摸屏維修技巧

    本文主要介紹了常見四種觸摸屏維修技巧以及觸摸屏常見故障與處理方法。
    發(fā)表于 10-23 09:27 ?2.2w次閱讀

    HarmonyOS開發(fā)文檔(二)

    HarmonyOS 視頻模塊支持視頻業(yè)務(wù)的開發(fā)和生態(tài)開放,開發(fā)者可以通過已開放的接口很容易地實現(xiàn)視頻媒體的播放、操作和新功能開發(fā)。視頻媒體的
    發(fā)表于 10-15 14:47 ?30次下載
    <b class='flag-5'>HarmonyOS</b><b class='flag-5'>開發(fā)</b>文檔(二)

    四種常見圖像濾波算法介紹

    作者丨一支程序媛@知乎 來源丨h(huán)ttps://zhuanlan.zhihu.com/p/279602383 編輯丨極市平臺 導(dǎo)讀 圖像濾波是一非常重要的圖像處理技術(shù),本文詳細介紹了四種
    的頭像 發(fā)表于 02-15 09:50 ?1w次閱讀

    分享四種常見的MOS管柵極驅(qū)動電路

    分享四種常見的MOS管柵極驅(qū)動電路,都用過嗎?
    的頭像 發(fā)表于 10-26 10:06 ?5206次閱讀

    走向?qū)嵱玫腁I編解碼闡述

    大家好,今天我分享的是走向?qū)嵱玫腁I圖像編解碼。本次將著重從 “走向”兩個字出發(fā),闡述AI編解碼研發(fā)的關(guān)鍵內(nèi)容和進展。
    發(fā)表于 06-15 09:19 ?968次閱讀
    走向?qū)嵱玫腁I<b class='flag-5'>編解碼</b>闡述