1# 如何转换图片格式
2
3## 场景说明
4当我们获取到图片或者视频的缩略图后,返回的是pixelMap,此时有开发者会有疑问如何将pixelMap转换成jpeg等其他格式的图片,其实使用image类中的packing方法就可以将pixelMap重新打包成新的格式(当前只支持jpeg,webp格式),再使用文件管理就可以将图片存入到应用的沙箱路径。本例即为大家介绍如何完成图片格式转换。
5
6## 运行环境
7本例基于以下环境开发,开发者也可以基于其他适配的版本进行开发:
8
9- IDE: DevEco Studio 4.0 Beta1
10- SDK: Ohos_sdk_public 4.0.7.5 (API Version 10 Beta1)
11
12## 效果呈现
13本例最终实现效果为:将工程资源文件中png格式的图片转换为jpg格式,并保存在设备中。由于本例不涉及UI讲解,所以不在此提供UI效果。
14
15## 实现思路
16本例中完成图片格式转换包含三个关键步骤,相关步骤及实现方案如下:
17- 获取到要转换图片的PixelMap数据:使用image的createPixelMap方法获取到图片的PixelMap数据。
18- 将图片的PixelMap重新打包转换为其他格式:使用packing方法进行打包,打包时可以设置格式、压缩质量等。
19- 将重新打包好的图片保存到应用目录:使用图库选择器photoViewPicker的相关功能以及file读写操作完成图片的保存。
20
21## 开发步骤
22由于本例重点讲解图片格式的转换,所以开发步骤会着重讲解相关实现,不相关的内容不做介绍,全量代码可参考完整代码章节。
231. 获取要转换图片的PixelMap数据。
24
25    先通过上下文context获取到资源管理器resourceManager,然后通过资源管理器获取到图片数据,然后获取图片的ArrayBuffer,最后通过ArrayBuffer创建imageSource,获取到pixelMap,完成图片解码。
26
27    具体代码如下:
28    ```ts
29    import common from '@ohos.app.ability.common';
30
31    @Entry
32    @Component
33    struct Index {
34      ...
35      context: common.UIAbilityContext = getContext(this) as common.UIAbilityContext
36      ...
37
38      async getPixelMap(){
39        // 获取resourceManager资源管理
40        const resourceMgr = this.context.resourceManager
41        // 获取rawfile文件夹下imagetransfer.PNG的ArrayBuffer
42        const fileData = await resourceMgr.getMediaContent($r('app.media.imagetransfer'))
43        const buffer = fileData.buffer
44        // 创建imageSource
45        const imageSource = image.createImageSource(buffer)
46        // 获取PixelMap
47        const pixelMap = await imageSource.createPixelMap()
48        return pixelMap
49      }
50      ...
51    }
52    ```
532. 将图片的PixelMap重新打包转换为其他格式。
54
55    先通过createImagePacker构建ImagePacker实例,再通过该实例调用packing方法进行打包,打包时传入获取到的PixelMap数据及重新打包的图片格式等相关配置信息。
56    具体代码如下:
57    ```ts
58    ...
59    @State src:PixelMap = undefined
60    ...
61    // 页面加载前将获取到的图片PixelMap数据赋值给状态变量src
62    async aboutToAppear() {
63      this.src = await this.getPixelMap()
64    }
65    ...
66    // 创建ImagePacker实例
67    let imagePackerApi = image.createImagePacker();
68    let options = {
69      // 设置重新打包的图片格式
70      format: 'image/jpeg',
71      quality: 98
72    };
73    // 打包时传入图片的PixelMap:src和图片打包选项:option,异步获取打包后的数据data
74    imagePackerApi.packing(this.src, options).then((data) => {
75      console.log('Succeeded in packing the image.');
76      }).catch(error => {
77      console.log('Failed to pack the image..');
78      ....
79    })
80    ```
813. 将重新打包好的图片保存到应用目录。
82
83    使用图库选择器photoViewPicker保存文件,保存时可以在保存界面选择保存路径并设定文件名。此时保存的是空文件,然后再使用file将重新打包的图片数据写入保存的文件中,保存完成后我们便可以在保存路径下找到转换格式后的图片文件了。
84    具体代码如下:
85    ```ts
86    ...
87    // 打包时传入图片的pixelmap:src和图片打包选项:option,异步获取打包后的数据data
88    imagePackerApi.packing(this.src, options).then((data) => {
89      // 创建文件管理器保存选项实例
90      let photoSaveOptions = new picker.PhotoSaveOptions();
91      // 保存文件名(可选)
92      photoSaveOptions.newFileNames = ["imageTransfer.jpg"];
93      let photoViewPicker = new picker.PhotoViewPicker();
94
95      // 保存时传入保存的文件名:photoSaveOptions
96      photoViewPicker.save(photoSaveOptions)
97        .then((photoSaveResult) => {
98          setTimeout(() => {
99            // 获取到保存文件的URI,后续进行文件读取等操作
100            this.uri = photoSaveResult[0];
101
102            fs.open(this.uri, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE).then((file) => {
103              // 将图片打包数据data写入保存的文件
104              fs.write(file.fd, data).then((number) => {
105                console.info("foo imagetest: write data to file succeed and size is:" + number);
106              }).catch((err) => {
107                console.info("foo imagetest: write data to file failed with error:" + err);
108              });
109              // 完成文件写入后,关闭文件
110              fs.close(file, (err) => {
111                if (err) {
112                  console.info("close file failed with error message: " + err.message + ", error code: " + err.code);
113                } else {
114                  console.info("close file success");
115                }
116              });
117            }).catch((err) => {
118              console.info("foo open file failed with error message: " + err.message + ", error code: " + err.code);
119            });
120
121          }, 200)
122
123        })
124        .catch((err) => {
125          console.error('PhotoViewPicker.save failed with err: ' + err);
126        })
127    })
128    ...
129    ```
130## 完整代码
131本例完整代码如下:
132```ts
133import image from '@ohos.multimedia.image';
134import fs from '@ohos.file.fs';
135import common from '@ohos.app.ability.common';
136import picker from '@ohos.file.picker';
137
138@Entry
139@Component
140struct Index {
141  @State src:PixelMap = undefined
142  context: common.UIAbilityContext = getContext(this) as common.UIAbilityContext
143  private  uri = null
144  // 页面加载前将获取到的图片PixelMap数据赋值给状态变量src
145  async aboutToAppear() {
146    this.src = await this.getPixelMap()
147  }
148
149  async getPixelMap(){
150    // 获取resourceManager资源管理
151    const resourceMgr = this.context.resourceManager
152    // 获取rawfile文件夹下httpimage.PNG的ArrayBuffer
153    const fileData = await resourceMgr.getMediaContent($r('app.media.contact6'))
154    const buffer = fileData.buffer
155    // 创建imageSource
156    const imageSource = image.createImageSource(buffer)
157    // 创建PixelMap
158    const pixelMap = await imageSource.createPixelMap()
159    return pixelMap
160    console.log('pixelMap  ' + JSON.stringify(this.src.getPixelBytesNumber()))
161  }
162
163  build() {
164    Row() {
165      Column() {
166        Button('转换图片格式:png->jpeg')
167          .onClick(() => {
168            // 创建ImagePacker实例
169            let imagePackerApi = image.createImagePacker();
170            // 设置重新打包的图片格式,及图片压缩质量
171            let options = {
172              format: 'image/jpeg',
173              quality: 98
174            };
175            // 打包时传入图片的pixelmap:src和图片打包选项:option,异步获取打包后的数据data
176            imagePackerApi.packing(this.src, options).then((data) => {
177              // 创建文件管理器保存选项实例
178              let photoSaveOptions = new picker.PhotoSaveOptions();
179              // 保存文件名(可选)
180              photoSaveOptions.newFileNames = ["imageTransfer.jpg"];
181              let photoViewPicker = new picker.PhotoViewPicker();
182              // 保存时传入保存的文件名:photoSaveOptions
183              photoViewPicker.save(photoSaveOptions)
184                .then((photoSaveResult) => {
185                  console.log('foo start')
186                  setTimeout(() => {
187                    // 获取到图片的URI后进行文件读取等操作
188                    this.uri = photoSaveResult[0];
189                    fs.open(this.uri, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE).then((file) => {
190                      // 将图片打包数据data写入保存的文件
191                      fs.write(file.fd, data).then((number) => {
192                        console.info("foo imagetest: write data to file succeed and size is:" + number);
193                      }).catch((err) => {
194                        console.info("foo imagetest: write data to file failed with error:" + err);
195                      });
196                      // 完成文件写入后,关闭文件
197                      fs.close(file, (err) => {
198                        if (err) {
199                          console.info("close file failed with error message: " + err.message + ", error code: " + err.code);
200                        } else {
201                          console.info("close file success");
202                        }
203                      });
204                    }).catch((err) => {
205                      console.info("foo open file failed with error message: " + err.message + ", error code: " + err.code);
206                    });
207                  }, 200)
208                })
209                .catch((err) => {
210                  console.error('PhotoViewPicker.save failed with err: ' + err);
211                })
212            })
213          })
214      }
215      .width('100%')
216    }
217    .height('100%')
218  }
219}
220```
221
222## 参考
223- [@ohos.multimedia.image (图片处理)](../application-dev/reference/apis-image-kit/js-apis-image.md)
224- [@ohos.file.fs (文件管理)](../application-dev/reference/apis-core-file-kit/js-apis-file-fs.md)
225- [@ohos.file.picker (选择器)](../application-dev/reference/apis-core-file-kit/js-apis-file-picker.md)