如何轉(zhuǎn)換圖片格式(使用packing將pixelMap重新打包為其他格式)
想了解更多關(guān)于開(kāi)源的內(nèi)容,請(qǐng)?jiān)L問(wèn):
如何轉(zhuǎn)換圖片格式
場(chǎng)景說(shuō)明
當(dāng)我們獲取到圖片或者視頻的縮略圖后,返回的是pixelMap,此時(shí)有開(kāi)發(fā)者會(huì)有疑問(wèn)如何將pixelMap轉(zhuǎn)換成jpeg等其他格式的圖片,其實(shí)使用image類中的packing方法就可以將pixelMap重新打包成新的格式(當(dāng)前只支持jpeg,webp格式),再使用文件管理就可以將圖片存入到應(yīng)用的沙箱路徑。本例即為大家介紹如何完成圖片格式轉(zhuǎn)換。
運(yùn)行環(huán)境
本例基于以下環(huán)境開(kāi)發(fā),開(kāi)發(fā)者也可以基于其他適配的版本進(jìn)行開(kāi)發(fā):
- IDE: DevEco Studio 4.0 Beta1
- SDK: Ohos_sdk_public 4.0.7.5 (API Version 10 Beta1)
效果呈現(xiàn)
本例最終實(shí)現(xiàn)效果為:將工程資源文件中png格式的圖片轉(zhuǎn)換為jpg格式,并保存在設(shè)備中。由于本例不涉及UI講解,所以不在此提供UI效果。
實(shí)現(xiàn)思路
本例中完成圖片格式轉(zhuǎn)換包含三個(gè)關(guān)鍵步驟,相關(guān)步驟及實(shí)現(xiàn)方案如下:
- 獲取到要轉(zhuǎn)換圖片的PixelMap數(shù)據(jù):使用image的createPixelMap方法獲取到圖片的PixelMap數(shù)據(jù)。
- 將圖片的PixelMap重新打包轉(zhuǎn)換為其他格式:使用packing方法進(jìn)行打包,打包時(shí)可以設(shè)置格式、壓縮質(zhì)量等。
- 將重新打包好的圖片保存到應(yīng)用目錄:使用圖庫(kù)選擇器photoViewPicker的相關(guān)功能以及file讀寫操作完成圖片的保存。
開(kāi)發(fā)步驟
由于本例重點(diǎn)講解圖片格式的轉(zhuǎn)換,所以開(kāi)發(fā)步驟會(huì)著重講解相關(guān)實(shí)現(xiàn),不相關(guān)的內(nèi)容不做介紹,全量代碼可參考完整代碼章節(jié)。
獲取要轉(zhuǎn)換圖片的PixelMap數(shù)據(jù)。
先通過(guò)上下文context獲取到資源管理器resourceManager,然后通過(guò)資源管理器獲取到圖片數(shù)據(jù),然后獲取圖片的ArrayBuffer,最后通過(guò)ArrayBuffer創(chuàng)建imageSource,獲取到pixelMap,完成圖片解碼。
具體代碼如下:
import common from '@ohos.app.ability.common';
@Entry
@Component
struct Index {
...
context: common.UIAbilityContext = getContext(this) as common.UIAbilityContext
...
async getPixelMap(){
// 獲取resourceManager資源管理
const resourceMgr = this.context.resourceManager
// 獲取rawfile文件夾下imagetransfer.PNG的ArrayBuffer
const fileData = await resourceMgr.getMediaContent($r('app.media.imagetransfer'))
const buffer = fileData.buffer
// 創(chuàng)建imageSource
const imageSource = image.createImageSource(buffer)
// 獲取PixelMap
const pixelMap = await imageSource.createPixelMap()
return pixelMap
}
...
}
將圖片的PixelMap重新打包轉(zhuǎn)換為其他格式。
先通過(guò)createImagePacker構(gòu)建ImagePacker實(shí)例,再通過(guò)該實(shí)例調(diào)用packing方法進(jìn)行打包,打包時(shí)傳入獲取到的PixelMap數(shù)據(jù)及重新打包的圖片格式等相關(guān)配置信息。
具體代碼如下:
...
@State src:PixelMap = undefined
...
// 頁(yè)面加載前將獲取到的圖片PixelMap數(shù)據(jù)賦值給狀態(tài)變量src
async aboutToAppear() {
this.src = await this.getPixelMap()
}
...
// 創(chuàng)建ImagePacker實(shí)例
let imagePackerApi = image.createImagePacker();
let options = {
// 設(shè)置重新打包的圖片格式
format: 'image/jpeg',
quality: 98
};
// 打包時(shí)傳入圖片的PixelMap:src和圖片打包選項(xiàng):option,異步獲取打包后的數(shù)據(jù)data
imagePackerApi.packing(this.src, options).then((data) => {
console.log('Succeeded in packing the image.');
}).catch(error => {
console.log('Failed to pack the image..');
....
})
將重新打包好的圖片保存到應(yīng)用目錄。
使用圖庫(kù)選擇器photoViewPicker保存文件,保存時(shí)可以在保存界面選擇保存路徑并設(shè)定文件名。此時(shí)保存的是空文件,然后再使用file將重新打包的圖片數(shù)據(jù)寫入保存的文件中,保存完成后我們便可以在保存路徑下找到轉(zhuǎn)換格式后的圖片文件了。
具體代碼如下:
...
// 打包時(shí)傳入圖片的pixelmap:src和圖片打包選項(xiàng):option,異步獲取打包后的數(shù)據(jù)data
imagePackerApi.packing(this.src, options).then((data) => {
// 創(chuàng)建文件管理器保存選項(xiàng)實(shí)例
let photoSaveOptions = new picker.PhotoSaveOptions();
// 保存文件名(可選)
photoSaveOptions.newFileNames = ["imageTransfer.jpg"];
let photoViewPicker = new picker.PhotoViewPicker();
// 保存時(shí)傳入保存的文件名:photoSaveOptions
photoViewPicker.save(photoSaveOptions)
.then((photoSaveResult) => {
setTimeout(() => {
// 獲取到保存文件的URI,后續(xù)進(jìn)行文件讀取等操作
this.uri = photoSaveResult[0];
fs.open(this.uri, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE).then((file) => {
// 將圖片打包數(shù)據(jù)data寫入保存的文件
fs.write(file.fd, data).then((number) => {
console.info("foo imagetest: write data to file succeed and size is:" + number);
}).catch((err) => {
console.info("foo imagetest: write data to file failed with error:" + err);
});
// 完成文件寫入后,關(guān)閉文件
fs.close(file, (err) => {
if (err) {
console.info("close file failed with error message: " + err.message + ", error code: " + err.code);
} else {
console.info("close file success");
}
});
}).catch((err) => {
console.info("foo open file failed with error message: " + err.message + ", error code: " + err.code);
});
}, 200)
})
.catch((err) => {
console.error('PhotoViewPicker.save failed with err: ' + err);
})
})
...
完整代碼
本例完整代碼如下:
import image from '@ohos.multimedia.image';
import fs from '@ohos.file.fs';
import common from '@ohos.app.ability.common';
import picker from '@ohos.file.picker';
@Entry
@Component
struct Index {
@State src:PixelMap = undefined
context: common.UIAbilityContext = getContext(this) as common.UIAbilityContext
private uri = null
// 頁(yè)面加載前將獲取到的圖片PixelMap數(shù)據(jù)賦值給狀態(tài)變量src
async aboutToAppear() {
this.src = await this.getPixelMap()
}
async getPixelMap(){
// 獲取resourceManager資源管理
const resourceMgr = this.context.resourceManager
// 獲取rawfile文件夾下httpimage.PNG的ArrayBuffer
const fileData = await resourceMgr.getMediaContent($r('app.media.contact6'))
const buffer = fileData.buffer
// 創(chuàng)建imageSource
const imageSource = image.createImageSource(buffer)
// 創(chuàng)建PixelMap
const pixelMap = await imageSource.createPixelMap()
return pixelMap
console.log('pixelMap ' + JSON.stringify(this.src.getPixelBytesNumber()))
}
build() {
Row() {
Column() {
Button('轉(zhuǎn)換圖片格式:png->jpeg')
.onClick(() => {
// 創(chuàng)建ImagePacker實(shí)例
let imagePackerApi = image.createImagePacker();
// 設(shè)置重新打包的圖片格式,及圖片壓縮質(zhì)量
let options = {
format: 'image/jpeg',
quality: 98
};
// 打包時(shí)傳入圖片的pixelmap:src和圖片打包選項(xiàng):option,異步獲取打包后的數(shù)據(jù)data
imagePackerApi.packing(this.src, options).then((data) => {
// 創(chuàng)建文件管理器保存選項(xiàng)實(shí)例
let photoSaveOptions = new picker.PhotoSaveOptions();
// 保存文件名(可選)
photoSaveOptions.newFileNames = ["imageTransfer.jpg"];
let photoViewPicker = new picker.PhotoViewPicker();
// 保存時(shí)傳入保存的文件名:photoSaveOptions
photoViewPicker.save(photoSaveOptions)
.then((photoSaveResult) => {
console.log('foo start')
setTimeout(() => {
// 獲取到圖片的URI后進(jìn)行文件讀取等操作
this.uri = photoSaveResult[0];
fs.open(this.uri, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE).then((file) => {
// 將圖片打包數(shù)據(jù)data寫入保存的文件
fs.write(file.fd, data).then((number) => {
console.info("foo imagetest: write data to file succeed and size is:" + number);
}).catch((err) => {
console.info("foo imagetest: write data to file failed with error:" + err);
});
// 完成文件寫入后,關(guān)閉文件
fs.close(file, (err) => {
if (err) {
console.info("close file failed with error message: " + err.message + ", error code: " + err.code);
} else {
console.info("close file success");
}
});
}).catch((err) => {
console.info("foo open file failed with error message: " + err.message + ", error code: " + err.code);
});
}, 200)
})
.catch((err) => {
console.error('PhotoViewPicker.save failed with err: ' + err);
})
})
})
}
.width('100%')
}
.height('100%')
}
}