• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# 编辑图片
2
3## 场景说明
4图片编辑是在应用中经常用到的功能,比如相机拍完照片后可以对照片进行编辑;截图后可以对截图进行编辑;可以对图库中的图片进行编辑等。本例即为大家介绍如何获取图片的pixelMap数据,并通过pixelMap对图片进行常见的编辑操作。
5
6## 效果呈现
7本例最终效果如下:
8
9![image-edit](figures/image-edit.gif)
10
11## 运行环境
12本例基于以下环境开发,开发者也可以基于其他适配的版本进行开发:
13
14- IDE: DevEco Studio 3.1 Release
15- SDK: Ohos_sdk_public 3.2.12.5(API Version 9 Release)
16
17## 实现思路
18本例中展示的是对资源文件中的图片进行编辑,编辑操作主要分为以下三步:
191. 对图片解码,获取到pixelMap:先通过上下文context获取到资源管理器resourceManager,然后通过资源管理器获取到图片数据,然后获取图片的ArrayBuffer,最后通过ArrayBuffer创建imageSource,获取到pixelMap,完成图片解码。
202. 编辑pixelMap:获取到pixelMap后就可以针对pixelMap进行裁剪、缩放、偏移、旋转、翻转、调节透明度等操作。
213. 将编辑好的pixelMap渲染显示出来:完成对pixelMap的编辑后,可以通过Image组件将编辑后的pixelMap渲染显示出来。
22
23## 开发步骤
24由于本例重点讲解图片编辑,所以开发步骤会着重讲解相关实现,不相关的内容不做介绍,全量代码可参考完整代码章节。
251. 对图片进行解码。
26
27    先通过上下文context获取到资源管理器resourceManager,然后通过资源管理器获取到图片数据,然后获取图片的ArrayBuffer,最后通过ArrayBuffer创建imageSource,获取到pixelMap,完成图片解码。
28    具体代码如下:
29    ```ts
30    async get_pixelmap(){
31      // 获取resourceManager资源管理
32      const context = getContext(this)
33      const resourceMgr = context.resourceManager
34      // 获取rawfile文件夹下httpimage.PNG的ArrayBuffer
35      const fileData = await resourceMgr.getMediaContent($r('app.media.httpimage'))
36      const buffer = fileData.buffer
37      // 创建imageSource
38      const imageSource = image.createImageSource(buffer)
39      // 创建PixelMap
40      const pixelMap = await imageSource.createPixelMap()
41      return pixelMap
42    }
43    ```
442. 编辑pixelMap。
45
46    分别通过以下方法对pixelMap进行裁剪、缩放、偏移、旋转、翻转、调节透明度等操作:crop、scale、translate、rotate、flip、opacity。
47    具体代码如下:
48    ```ts
49    // 对pixelMap进行裁剪
50    async crop_image(){
51      let pixelMap = await this.get_pixelmap()
52      pixelMap.crop({x:0,y:0,size:{height:300,width:300}})
53      this.imagePixelMap = pixelMap
54    }
55    // 对pixelMap进行缩放
56    async scale_image(){
57      let pixelMap = await this.get_pixelmap()
58      pixelMap.scale(0.5,0.5)
59      this.imagePixelMap = pixelMap
60    }
61    // 对pixelMap进行偏移
62    async translate_image(){
63      let pixelMap = await this.get_pixelmap()
64      pixelMap.translate(100,100);
65      this.imagePixelMap = pixelMap
66    }
67    // 对pixelMap进行旋转
68    async rotate_image(){
69      let pixelMap = await this.get_pixelmap()
70      pixelMap.rotate(90);
71      this.imagePixelMap = pixelMap
72    }
73    // 对pixelMap进行翻转
74    async flip_image(){
75      let pixelMap = await this.get_pixelmap()
76      pixelMap.flip(false, true);
77      this.imagePixelMap = pixelMap
78    }
79    // 对pixelMap进行透明度调整
80    async opacity_image(){
81      let pixelMap = await this.get_pixelmap()
82      pixelMap.opacity(0.5);
83      this.imagePixelMap = pixelMap
84    }
85    ```
863. 通过Image组件将编辑后的pixelMap渲染显示出来。
87
88    第2步中将编辑好的pixelMap传递给状态变量imagePixelMap,本步中直接将imagePixelMap传入Image组件进行渲染显示。
89    具体代码如下:
90    ```ts
91    if(!this.edit){
92      Row(){
93        Image($r('app.media.httpimage')).objectFit(ImageFit.None)
94      }.width('100%').height('50%').backgroundColor('#F0F0F0')
95    }else{
96      Row(){
97        // 将编辑好的pixelMap传递给状态变量imagePixelMap后,通过Image组件进行渲染
98        Image(this.imagePixelMap).objectFit(ImageFit.None)
99      }.width('100%').height('50%').backgroundColor('#F0F0F0')
100    }
101    ```
102
103## 完整代码
104本例完整代码如下:
105```ts
106import image from '@ohos.multimedia.image';
107
108@Entry
109@Component
110struct ImageEdit{
111  @State imagePixelMap:PixelMap = undefined
112  @State edit:boolean = false
113
114  @Builder buttonModel($$:{textContent,action}){
115    Button($$.textContent)
116      .fontSize(14)
117      .height(30)
118      .width(60)
119      .borderRadius(10)
120      .backgroundColor('#E8A027')
121      .onClick(()=>{
122        $$.action
123        this.edit = true
124      })
125  }
126
127  async get_pixelmap(){
128    // 获取resourceManager资源管理
129    const context = getContext(this)
130    const resourceMgr = context.resourceManager
131    // 获取rawfile文件夹下httpimage.PNG的ArrayBuffer
132    const fileData = await resourceMgr.getMediaContent($r('app.media.httpimage'))
133    const buffer = fileData.buffer
134    // 创建imageSource
135    const imageSource = image.createImageSource(buffer)
136    // 创建PixelMap
137    const pixelMap = await imageSource.createPixelMap()
138    return pixelMap
139  }
140
141  // 对pixelMap进行裁剪
142  async crop_image(){
143    let pixelMap = await this.get_pixelmap()
144    pixelMap.crop({x:0,y:0,size:{height:300,width:300}})
145    this.imagePixelMap = pixelMap
146  }
147
148  // 对pixelMap进行缩放
149  async scale_image(){
150    let pixelMap = await this.get_pixelmap()
151    pixelMap.scale(0.5,0.5)
152    this.imagePixelMap = pixelMap
153  }
154
155  // 对pixelMap进行偏移
156  async translate_image(){
157    let pixelMap = await this.get_pixelmap()
158    pixelMap.translate(100,100);
159    this.imagePixelMap = pixelMap
160  }
161
162  // 对pixelMap进行旋转
163  async rotate_image(){
164    let pixelMap = await this.get_pixelmap()
165    pixelMap.rotate(90);
166    this.imagePixelMap = pixelMap
167  }
168
169  // 对pixelMap进行翻转
170  async flip_image(){
171    let pixelMap = await this.get_pixelmap()
172    pixelMap.flip(false, true);
173    this.imagePixelMap = pixelMap
174  }
175
176  // 对pixelMap进行透明度调整
177  async opacity_image(){
178    let pixelMap = await this.get_pixelmap()
179    pixelMap.opacity(0.5);
180    this.imagePixelMap = pixelMap
181  }
182
183  build(){
184    Column(){
185      if(!this.edit){
186        Row(){
187          Image($r('app.media.httpimage')).objectFit(ImageFit.None)
188        }.width('100%').height('50%').backgroundColor('#F0F0F0')
189      }else{
190        Row(){
191          // 将编辑好的pixelMap传递给状态变量imagePixelMap后,通过Image组件进行渲染
192          Image(this.imagePixelMap).objectFit(ImageFit.None)
193        }.width('100%').height('50%').backgroundColor('#F0F0F0')
194      }
195
196      Flex({wrap:FlexWrap.Wrap,justifyContent:FlexAlign.SpaceEvenly}){
197        this.buttonModel({textContent:'裁剪',action:this.crop_image()})
198        this.buttonModel({textContent:'缩放',action:this.scale_image()})
199        this.buttonModel({textContent:'偏移',action:this.translate_image()})
200        this.buttonModel({textContent:'旋转',action:this.rotate_image()})
201        this.buttonModel({textContent:'翻转',action:this.flip_image()})
202        this.buttonModel({textContent:'透明度',action:this.opacity_image()})
203        Button('还原')
204          .fontSize(14)
205          .height(30)
206          .width(60)
207          .borderRadius(10)
208          .margin({top:20})
209          .backgroundColor('#A4AE77')
210          .onClick(()=>{
211            this.edit = false
212          })
213      }
214      .margin({top:100})
215      .height('100%')
216      .width('100%')
217    }
218    .height('100%')
219    .width('100%')
220  }
221}
222```
223## 参考
224- [图片解码](../application-dev/media/image-decoding.md)
225- [图片变换](../application-dev/media/image-transformation.md)
226- [Image组件](../application-dev/reference/apis-arkui/arkui-ts/ts-basic-components-image.md)
227