日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

HarmonyOS第三方组件——鸿蒙图片裁剪组件ohos-Image-Cropper

發布時間:2024/1/8 编程问答 97 豆豆
生活随笔 收集整理的這篇文章主要介紹了 HarmonyOS第三方组件——鸿蒙图片裁剪组件ohos-Image-Cropper 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

前言

基于安卓的平臺的圖片裁剪組件(https://github.com/ArthurHub/Android-Image-Cropper),實現了鴻蒙平臺的遷移和重構,代碼已經開源到(https://gitee.com/isrc_ohos/android-image-cropper_ohos),歡迎各位開發者下載使用并提出寶貴意見~

背景

ohos-Image-Cropper組件是個簡單、靈活、高效的圖片裁剪工具,支持圖片在裁剪前進行裁剪框移動、旋轉、翻轉(水平、垂直)的操作,并將最終裁剪結果反饋給用戶。

Sample解析

在Sample中,向用戶提供了三個界面,分別是:初始界面、功能選擇界面、效果展示界面。初始界面包含一個按鈕,點擊可進入功能選擇界面。功能選擇界面可對圖片進行裁剪、旋轉、水平翻轉、垂直翻轉等操作。當用戶選擇圖片裁剪功能時,會跳轉到效果展示界面,展示裁剪后的圖片。

1. 如何跳轉至功能選擇界面?

CropImage是個工具類,可以實現頁面跳轉功能。此處可以將下面代碼放入Button按鈕的點擊事件中,執行下面代碼可以實現從用戶的初始界面跳轉至功能選擇界面。

CropImage.activity() ?//初始化CropImage類 ? ? ? ? .setContext(this)//設置上下文 ? ? ? ? ? ? ? .setSource(ResourceTable.Media_baochi)//傳入被裁減圖片的ID ? ? ? ? .setBundleName("com.huawei.mytestproject")//傳入包名 ? ? ? ? .setAbilityName("com.huawei.mytestproject.MainAbility")//傳入類名 ? ? ? ? .setRequset_code(1234)//請求參數設置 ? ? ? ? .start(super.getAbility(),this);//啟動跳轉

關于上代碼有三點需要注意,一是:為了方便大家使用模擬器運行Sample,被裁減圖片使用在鴻蒙的資源管理器ResourceTable中注冊過的圖片。圖片需放在APP項目資源文件夾resource/base/media下面,ResourceTable會掃描資源文件夾,并為每個資源注冊一個int型的數值作為資源id。圖1展示了圖片所在位置,圖二展示了圖片在ResourceTable中的注冊。二是:代碼中傳入的包名和類名是用于指定圖片裁剪后返回的Ability(即效果展示界面)。三是:被裁減圖片必須為正方形。

圖1. 被裁減圖片存放位置

圖2. 被裁減圖片在ResourceTable中的注冊

2. 如何跳轉至效果展示界面?

當裁剪完畢時,會根據用戶提供的包名和類名跳轉至效果展示界面,來展示裁剪后的圖片。具體使用代碼參照如下:

//裁剪方法 private void crop(Intent intentOriginal) { ... ? ? Intent intent = new Intent(); ... ? ? Operation operation = new Intent.OperationBuilder() ? ? ? ? ? ? .withDeviceId("") ? ? ? ? ? ?//指定圖片裁剪后返回的Ability包名和類名 ? ? ? ? ? ? .withBundleName(intentOriginal.getStringParam("bundleName")) ? ? ? ? ? ? .withAbilityName(intentOriginal.getStringParam("abilityName")) ? ? ? ? ? ? .build(); ? ? intent.setOperation(operation);// 把operation設置到intent中 ? startAbility(intent);//跳轉方法 }

3. 如何獲得裁剪圖片? ? ?

裁剪后的圖片是位圖格式PixelMap(原因見Library解析),本節介紹了裁剪后位圖的兩種獲取方法。

方法一 ?

CropImage.handleImage(int result_code , Component image);

此方法需要傳入一個新創建的Component,用以接收被裁剪后的位圖,用戶后續可以把Component加入到自己的布局中進行顯示。 其中result_code為結果參數,通過這個參數判斷裁剪是否成功。參數result_code可以從intent中獲得,如下面一行代碼所示:

int result_code = result.getIntParam("result_code" , 0);

方法二 ?

PixelMap croppedPixelMap = CropImage.getCroppedPixelMap();

此方法可以返回裁剪后的位圖,用戶可以根據需要自行處理。

4. Sample效果

(1)初始界面跳轉至功能選擇界面 通過點擊startCrop按鈕進入功能選擇界面,如圖3所示。

圖3 初始界面跳轉至功能選擇界面

(2)功能選擇界面跳轉至效果展示界面 裁剪成功后,將跳轉至效果展示界面,如圖4所示。此時startCrop按鈕依然存在,可以繼續對圖片進行裁剪。

圖4 功能選擇界面跳轉至效果展示界面

裁剪取消后跳轉至效果展示界面,如圖5所示。

圖5 裁剪取消后跳轉至效果展示界面

Library解析

Library解析部分重點介紹本組件核心功能的實現原理,包括圖片裁剪、裁剪框移動、圖片旋轉、圖片翻轉(水平、垂直)四個功能。

1. 圖片裁剪

圖6 圖片裁剪的原理 ? ?

圖片裁剪的主要原理是解碼和坐標對應,以下通過三個步驟對裁剪的過程進行詳細講解:

1) 如圖6所示,被裁減的圖片①為JPG格式(目前支持JPEG、PNG、GIF、HEIF、WebP和BMP格式),不可以直接用于圖像裁剪、翻轉、旋轉等操作,因此,采用工具類ImageSource將JPG圖片解碼為對應的位圖②,用戶可以直接對位圖進行上述操作。

//實例化一個資源選項類 ImageSource.SourceOptions options = new ImageSource.SourceOptions(); //選擇解碼jpg圖片 options.formatHint = "image/jpg"; //實例化一個解碼選項 ImageSource.DecodingOptions decodingOptions = new ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?ImageSource.DecodingOptions(); ? ? ? ? ? ? ? //設置解碼后的位圖為可以編輯 decodingOptions.editable = true; //解碼選項可以傳入一個矩形,如果不傳,默認解碼完整的圖片 //decodingOptions.desiredRegion = new Rect(0 , 0 , 100 , 100); try { Resource asset = assetManager.openRawFile(); ? ? ?//圖片資源 ImageSource source = ImageSource.create(asset, options); ? ? ?//返回解碼后的位圖 ?return Optional.ofNullable(source.createPixelmap(decodingOptions)).get(); }...

2) 在位圖②中,用戶拖動裁剪框選擇需要裁剪的位置,此位置確定后按照坐標原理映射到JPG圖片①中,如①中的虛線裁剪框所示。 ? ?

圖片在裁剪之前,若沒有發生旋轉、翻轉等操作,實線裁剪框在位圖中的位置和虛線裁剪框在JPG圖中的位置是一樣的,此時JPG圖片中的裁剪區域獲取較為簡單。 ? ?

圖片在裁剪前發生旋轉、翻轉等操作時,采用圖7所示的方法獲取JPG圖片中的裁剪區域。以裁剪前圖片順時針旋轉90度為例,將圖片所在坐標系的左上、右上、右下、左下的點分別設置為:0、1、2、3,定義圖片的左上角為A點,左下角為B點,此時A=0、B=3。當圖片順時針旋轉90度以后,圖片的A點轉到了右上角,B點轉到了左上角,此時A=1、B=0。 ? ?

由此方法可以推算出AB邊的位置,計算出裁剪框在位圖中相對于AB邊的位置,便可確定JPG圖中需要裁剪的區域,實現坐標映射。

圖7 位圖的AB邊確定

3) 在①中,對虛線裁剪框對應的區域進行解碼,得到用戶想要的裁剪圖片的位圖③ ,裁剪功能完成。

//解碼 try { Resource asset = assetManager.openRawFile(); ImageSource source = ImageSource.create(asset, options); //返回解碼后的位圖 return Optional.ofNullable(source.createPixelmap(decodingOptions)).get(); } catch (IOException e) { e.printStackTrace(); } return Optional.empty();

2. 裁剪框移動

裁剪框移動的原理是:為裁剪框綁定一個單指點擊事件,如果監聽到了單指點擊,就獲取當前裁剪框的大小和位置,單擊點移動后,刷新裁剪框的繪制方法,以新的單擊點為中心重新繪制一個裁剪框,記錄新的裁剪框的大小和位置信息,從而實現裁剪框的移動,具體代碼如下,效果如圖8所示。

//滑動監聽 public void setSlideListener() { ? ? ? //初始化滑動監聽 ? ? ?mCropBound.setTouchEventListener(new Component.TouchEventListener() { ?//創建一個RectFloat用來記錄滑動之后的位置 ?RectFloat mScrolledClipBoundRect; ?@Override ?public boolean onTouchEvent(Component component, TouchEvent touchEvent) { ?//獲得當前手指點擊位置,此位置為相對于整個屏幕的坐標,屏幕左上角x=0,y=0; MmiPoint position = touchEvent.getPointerPosition(0); ?float x = position.getX(); ?float y = position.getY(); //獲得當前裁剪框的寬和高 ? ? ? ?float width = getCropBoundWidth(); ? float height = getCropBoundHeight(); ?//獲得當前圖片的位置,圖片所在的上下左右邊的位置 ? ? ? ? int left = mBitmapUtils.getPositionLeft(); ?int top = mBitmapUtils.getPositionTop(); ?int right = mBitmapUtils.getPositionRight(); ?int bottom = mBitmapUtils.getPositionBottom(); ?//獲得裁剪框位置,裁剪框所在的上下左右邊的位置 ? ? ? ? float cropBoundLeft = mCropRect.left; ?float cropBoundTop = mCropRect.top; ?float cropBoundRight = mCropRect.right; ?float cropBoundBottom = mCropRect.bottom; //判斷裁剪框的位置,裁剪框不能超過圖片的邊界 ?if ((right > (x + width / 2)) && ?((x - width / 2) > left) && ?(bottom > (y + height / 2)) && ?((y - height / 2) > top) ?) { ? ? ?//判斷裁剪框的位置,點擊事件必須在裁剪框內才可以移動裁剪框 ?if((cropBoundRight - width/10 > x) && ?(x > cropBoundLeft + width/10) && ?(cropBoundBottom - height/10> y) && ?(y > cropBoundTop + height/10)){ ? ? ? //記錄新的裁剪框的位置信息 ?mScrolledClipBoundRect = new RectFloat(x - width / 2.0f, y - height / 2.0f, x + width / 2.0f, y + height / 2.0f); ? ? ? ?//更新裁剪框 ?updateClipBound(mCropBound, mScrolledClipBoundRect); ? ? ? ? //更新記錄裁剪框位置信息的矩形 ?mCropRect = mScrolledClipBoundRect; return false; ?} ?} ?return false; ?} ?}); }

圖8 裁剪框移動

3. 圖片旋轉

JPG格式的圖片不可以執行旋轉的操作,此處需要將JPG圖片轉換為位圖。左上角水平向右為位圖的X軸正方向,左上角垂直向下為位圖的Y軸正方位圖。位圖繪制完成后進行旋轉操作,以圖片本身中心為中心點旋轉90度。具體代碼如下,效果如圖9所示。

private void rotate(Canvas canvas) { ?//以圖片中心為旋轉中心,旋轉90度 ?canvas.rotate(90 , mCropWindowHandler.getWindowWidth()/2 , mCropWindowHandler.getWindowWidth()/2); ? }

圖9 圖片旋轉

4. 圖片翻轉

JPG格式的圖片不可以執行翻轉的操作,此處需要將JPG圖片轉換為位圖,后續對位圖進行操作。

1)水平翻轉

左上角水平向右為位圖的X軸正方向,左上角垂直向下為位圖的Y軸正方向。將位圖先向X軸負方向縮放一倍,其大小沒有變化,但是坐標發生變化,位圖實現了以Y軸為對稱軸向左翻轉,最后向X軸正方向(即向右)移動圖片寬度的距離,實現位圖的水平翻轉。具體代碼如下,效果如圖10所示。

//水平翻轉方法(Canvas倒序執行) private void horizontalFilp(Canvas canvas){ ?canvas.save(); ?//向x軸正方向移動canvas.translate(mCropWindowHandler.getWindowWidth() , 0); ?//向x軸負方向縮放一倍 canvas.scale(-1f , 1f); }

圖10 圖片水平翻轉

2)垂直翻轉

坐標系的設置與水平翻轉相同。將位圖先向Y軸負方向縮放一倍,其大小沒有變化,但是坐標點發生變化,位圖實現了以X軸為對稱軸向上翻轉,然后向Y軸正方向(即向下)移動圖片高度的距離,實現圖片的垂直翻轉。具體代碼如下,效果圖如圖11所示。

//豎直翻轉方法(Canvas倒序執行) private void verticalFilp(Canvas canvas){ ?canvas.save(); ?//向y軸正方向移動 ?canvas.translate(0 , mCropWindowHandler.getWindowWidth()); ?//向y軸負方向縮放一倍 ?canvas.scale(1f , -1f); }

圖11 圖片垂直翻轉

5. 方法重寫 ?

由于鴻蒙與安卓存在大量的UI構建方式差異,因此ohos-Image-Cropper組件只參考了Android-Image-Cropper所實現的功能點,完全重寫了所有的實現方法。感興趣的小伙伴們可以自行比較源碼。

項目貢獻人

趙柏屹 鄭森文 朱偉 陳美汝 張馨心 王佳思

總結

以上是生活随笔為你收集整理的HarmonyOS第三方组件——鸿蒙图片裁剪组件ohos-Image-Cropper的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。