鴻蒙基于圖像模塊實現(xiàn)圖庫圖片的四種常見操作開發(fā)分享
51CTO和華為官方合作共建的鴻蒙技術(shù)社區(qū)
1. 項目介紹
HarmonyOS圖像模塊支持圖像業(yè)務(wù)的開發(fā),常見功能如圖像解碼、圖像編碼、基本的位圖操作、圖像編輯等。當(dāng)然,也支持通過接口組合來實現(xiàn)更復(fù)雜的圖像處理邏輯。本教程以圖庫圖片中旋轉(zhuǎn)、剪裁、縮放、鏡像四種常見操作為例,給大家介紹HarmonyOS圖像編解碼的相關(guān)開發(fā)指導(dǎo)。
2. 將圖片轉(zhuǎn)換為PixelMap
圖像解碼就是將所支持格式的存檔圖片解碼成統(tǒng)一的PixelMap圖像,用于后續(xù)圖像顯示或其他處理,比如旋轉(zhuǎn)、縮放、剪裁等。當(dāng)前支持格式包括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)按鈕會進(jìn)行90度的旋轉(zhuǎn),縮放是按照2:1的比例進(jìn)行縮放,剪裁是保證寬度不變的情況下對高度進(jìn)行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. 圖片鏡像操作
圖片鏡像操作就是對圖片以縱坐標(biāo)為軸制作對稱圖片。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. 完整示例
以手機(jī)為例,初始化頁面如圖1所示,依次點擊按鈕可以實現(xiàn)圖片的旋轉(zhuǎn)、剪裁、縮放、鏡像,效果如下所示(您需要準(zhǔ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);
- }
- }
布局代碼如下:
- <?xml version="1.0" encoding="utf-8"?>
- <DirectionalLayout
- xmlns:ohos="http://schemas.huawei.com/res/ohos"
- ohos:height="match_parent"
- ohos:width="match_parent"
- ohos:orientation="vertical">
- <Text
- ohos:height="match_content"
- ohos:width="match_content"
- ohos:layout_alignment="horizontal_center"
- ohos:text="HarmonyOS圖像開發(fā)"
- ohos:text_size="80"
- ohos:top_margin="40vp"
- />
- <DirectionalLayout
- xmlns:ohos="http://schemas.huawei.com/res/ohos"
- ohos:height="match_content"
- ohos:width="match_content"
- ohos:layout_alignment="horizontal_center"
- ohos:orientation="horizontal"
- ohos:top_margin="20vp">
- <Button
- ohos:id="$+id:whirl_image"
- ohos:height="match_content"
- ohos:width="match_content"
- ohos:background_element="$graphic:background_button"
- ohos:padding="12vp"
- ohos:right_margin="5vp"
- ohos:text="旋轉(zhuǎn)"
- ohos:text_size="20vp"
- ohos:top_margin="10vp">
- </Button>
- <Button
- ohos:id="$+id:crop_image"
- ohos:height="match_content"
- ohos:width="match_content"
- ohos:background_element="$graphic:background_button"
- ohos:left_margin="5vp"
- ohos:padding="12vp"
- ohos:text="剪裁"
- ohos:text_size="20vp"
- ohos:top_margin="10vp">
- </Button>
- <Button
- ohos:id="$+id:scale_image"
- ohos:height="match_content"
- ohos:width="match_content"
- ohos:background_element="$graphic:background_button"
- ohos:left_margin="5vp"
- ohos:padding="12vp"
- ohos:text="縮放"
- ohos:text_size="20vp"
- ohos:top_margin="10vp">
- </Button>
- <Button
- ohos:id="$+id:mirror_image"
- ohos:height="match_content"
- ohos:width="match_content"
- ohos:background_element="$graphic:background_button"
- ohos:left_margin="5vp"
- ohos:padding="12vp"
- ohos:text="鏡像"
- ohos:text_size="20vp"
- ohos:top_margin="10vp"/>
- </DirectionalLayout>
- <Image
- ohos:id="$+id:image"
- ohos:height="match_content"
- ohos:width="match_content"
- ohos:image_src="$media:shanghai.jpg"
- ohos:layout_alignment="horizontal_center"
- ohos:top_margin="20vp">
- </Image>
- </DirectionalLayout>
此外您還需在resource/base/graphic目錄下添加background_button.xml
- <?xml version="1.0" encoding="utf-8"?>
- <shape xmlns:ohos="http://schemas.huawei.com/res/ohos"
- ohos:shape="rectangle">
- <corners
- ohos:radius="40"/>
- <solid
- ohos:color="#e9e9e9"/>
- </shape>
說明
以上代碼僅demo演示參考使用,產(chǎn)品化的代碼需要考慮數(shù)據(jù)校驗和國際化。
51CTO和華為官方合作共建的鴻蒙技術(shù)社區(qū)