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文章
1967瀏覽量
30035
發布評論請先 登錄
相關推薦
評論