前言
Apple從iPhone6s開始支持Live Photo拦英。Live Photo 會(huì)錄下拍照前后 1.5 秒所發(fā)生的一切,因此用戶獲得的不僅僅是一張精美照片院峡,還有拍照前后時(shí)刻的動(dòng)作和聲音兴使。具體的操作可以參見拍照和編輯。
本文接下來要介紹的是如何在項(xiàng)目開發(fā)過程中使用Live Photo以及兼容其他平臺(tái)使用Live Photo照激。這些平臺(tái)包括iOS发魄、Web和Android。接下來就開始進(jìn)行介紹。
正文
先了解幾個(gè)概念励幼。
HEVC:全稱High Efficiency Video Coding汰寓。它是一種高效的視頻編碼,是符合行業(yè)標(biāo)準(zhǔn)的下一代視頻編碼技術(shù)苹粟,繼承自H.264編碼有滑。Apple想要添加新的功能特性,但是當(dāng)前的H.264已經(jīng)無法滿足Apple的需求嵌削,因此HEVC應(yīng)運(yùn)而生毛好。
HEIF:全稱High Efficiency Image File(Format),是一種高效率的圖片文件格式苛秕,是中靜止圖像和圖像序列的現(xiàn)代容器格式睛榄。
蘋果從iOS11開始已經(jīng)默認(rèn)啟動(dòng)了HEVC電影和HEIF圖像存儲(chǔ)。也就是說iOS11以及以后版本的手機(jī)拍攝的圖片默認(rèn)存儲(chǔ)的格式都是HEIF想帅。但是我們可以嘗試將手機(jī)拍攝的圖片發(fā)送給其他人,你會(huì)發(fā)現(xiàn)圖片的格式依然是JPG啡莉。這是Apple做了兼容港准,讓拍攝的照片更好地跨平臺(tái)支持。但是如果你用Mac上的Photo(應(yīng)用)將Live Photo以原圖的形式導(dǎo)出咧欣,你會(huì)發(fā)現(xiàn)它導(dǎo)出的內(nèi)容不再是JPG格式的文件浅缸,而是一個(gè)HEIC文件+一個(gè)mov文件。
Apple其實(shí)是通過圖片+視頻的方式實(shí)現(xiàn)了Live Photo魄咕。
先簡(jiǎn)單介紹多平臺(tái)展示Live Photo的思路:
蘋果手機(jī)用戶將Live Photo上傳到服務(wù)器衩椒,此時(shí)上傳的是一張圖片+視頻。當(dāng)展示的時(shí)候分以下幾種情況:
- 對(duì)于蘋果手機(jī)的用戶哮兰,可以從服務(wù)端獲取圖片+視頻毛萌,然后將其合成Live Photo進(jìn)行展示。
- 對(duì)于Android手機(jī)用戶喝滞,可以模擬Live Photo阁将,將圖片覆蓋到視頻上,然后進(jìn)行隱藏展示播放右遭。 當(dāng)播放時(shí)隱藏圖片做盅,讓視頻播放;當(dāng)停止播放時(shí)顯示圖片覆蓋視頻窘哈,停止視頻播放吹榴。
- 對(duì)于Web用戶,可以直接使用Apple官方提供的LivePhotosKit JS滚婉,按照其使用方法將圖片和視頻加載到DOM元素中展示图筹。Apple也提供了官方的一個(gè)Web展示Live Photo的Demo,點(diǎn)擊這里查看满哪。
接下來分平臺(tái)進(jìn)行操作處理婿斥。
iOS
首先劝篷,我們?nèi)绻胍謩?dòng)獲取Live Photo的源文件,蘋果推薦了下面幾種方式:
1.Using macOS Image Capture
- Connect your iOS device to your Mac.(使用數(shù)據(jù)線將設(shè)備連接到你的Mac)
- Select the Live Photo you wish to import from your device to your local file system.(選擇你想要導(dǎo)出到你本地文件系統(tǒng)的Live Photo)
- Choose the destination folder and click on Import.(選擇你的目標(biāo)文件夾民宿,然后點(diǎn)擊導(dǎo)入)
2.Using macOS Photos
- Connect your iOS device to your Mac.(將你的iOS設(shè)備和Mac相連)
- Import your photos into the Photos application.(把你手機(jī)上的圖片導(dǎo)入到Photos應(yīng)用程序中)
- Select the Live Photo you wish to export.(選中你想要導(dǎo)入的Live Photo)
- Use File > Export > Export Unmodified Original to export to your file system.(導(dǎo)出娇妓,選擇導(dǎo)出一張未修改的原件即可)
3.Using Windows 10 File Explorer
- Ensure that iTunes for Windows is installed. You can download it from here: http://www.apple.com/itunes/download/
- Open File Explorer. This can be opened by pressing the Windows Key and E at the same time.
- Connect your iOS device to your PC.
- You should see your iOS device in the "This PC" folder.
- Navigate to the following folder: (your device) > Internal Storage > DCIM and look for the Live Photo you wish to import.
- Your Live Photo will be stored as a pair of files: a JPG file and a MOV file.
- Drag the pair of files to your local file system.
導(dǎo)出之后,得到了兩個(gè)文件:一個(gè)是后綴為HEIC的圖像文件活鹰,一個(gè)是mov后綴的視頻文件哈恰。此時(shí),便可以手動(dòng)將圖片+視頻上傳到Server志群,然后供其他端使用着绷。
如果是用戶使用自己的iOS設(shè)備上傳圖片,我們可以先通過PHAssetCollection或者PHAsset獲取圖片锌云,這里有個(gè)demo:我通過PHAsset.fetchAssets(with:photoOptions)可以獲取手機(jī)上面所有的圖片荠医。還有一個(gè)PHAssetCollection的類,它代表圖庫(kù)中的組桑涎,例如時(shí)刻彬向、用戶創(chuàng)建的相冊(cè)或者是smart album。我們可以使用該類獲取所有的smartAlbum集合:
var smartAlbums: PHFetchResult<PHAssetCollection>! //smart albums
smartAlbums = PHAssetCollection.fetchAssetCollections(with: .smartAlbum, subtype: .albumRegular, options: nil)
這里的.smartAlbum就是圖庫(kù)中的組的集合攻冷,是一個(gè)枚舉:
public enum PHAssetCollectionType : Int {
case album
case smartAlbum
case moment
}
此時(shí)拿到的smartAlbums就是一組group娃胆,每個(gè)group中又包含了符合該組條件的圖片例如:
左邊Smart Albums是獲取到的smartAlbums,里面對(duì)圖片做了智能分類等曼,包括最近刪除的里烦、屏幕快照、Live Photos禁谦、Videos等等胁黑。右邊是點(diǎn)擊Live Photos進(jìn)入的頁(yè)面。里面全部是Live Photo州泊。圖片縮略圖頁(yè)面的數(shù)據(jù)是通過上一個(gè)頁(yè)面?zhèn)魅氲膅roup中單個(gè)collection:
imgListVC.photosList = PHAsset.fetchAssets(in: smartAlbums.object(at: indexPath.row), options: nil)
這里的PHAsset.fetchAssets是從某個(gè)PHAssetCollection中獲取該Collection中的所有圖片集合别厘,返回結(jié)果:
var photosList: PHFetchResult<PHAsset>? = nil
也就是PHFetchResult類型,是一個(gè)結(jié)果集拥诡。拿到結(jié)果集之后触趴,便可以在圖片列表頁(yè)面展示:
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let collectionViewCell = collectionView.dequeueReusableCell(withReuseIdentifier: CellIdentifier, for: indexPath) as! ImageCollectionCell
let asset = photosList?.object(at: indexPath.row)
if (asset?.mediaSubtypes.contains(.photoLive))! {
collectionViewCell.badgeImage = PHLivePhotoView.livePhotoBadgeImage(options: .overContent)
}
imageManager.requestImage(for: asset!, targetSize: CGSize.init(width: 80, height: 80), contentMode: .aspectFill, options: nil, resultHandler: { image, _ in
// The cell may have been recycled by the time this handler gets called;
// set the cell's thumbnail image only if it's still showing the same asset.
collectionViewCell.smallImage = image
})
return collectionViewCell
}
這里使用的UICollectionView充當(dāng)容器。collectionViewCell.badgeImage(自定義的image渴肉,用于展示左上角的live photo標(biāo)識(shí))的獲取方式很獨(dú)特冗懦,是PhotosUI中自帶的API獲取的:
PHLivePhotoView.livePhotoBadgeImage(options: .overContent)
PHLivePhotoView是繼承與UIview的一個(gè)子類,可以把它理解為UIImageView仇祭,只不過UIImageView是用于展示靜態(tài)圖片披蕉,而PHLivePhotoView用于展示Live Photo。該類有一個(gè)livePhotoBadgeImage的方法用于獲取live photo的標(biāo)識(shí)圖片,選項(xiàng).overContent是Live Photo正常展示的角標(biāo),而.liveOff則是在角標(biāo)上添加了斜杠没讲,可自行嘗試眯娱。
接下來就是獲取要展示的圖片,這里使用到了PHCachingImageManager類爬凑,該類主要是提供用于檢索或者生成預(yù)覽圖像徙缴。所以展示的預(yù)覽圖就是通過該類生成的。調(diào)用它的requestImage方法嘁信,將asset傳入于样,便可獲UIImage對(duì)象。
當(dāng)點(diǎn)擊某個(gè)圖片進(jìn)去詳情頁(yè)面時(shí)潘靖,通過傳入的asset便可獲取Live Photo穿剖,并在PHLivePhotoView上展示:
PHImageManager.default().requestLivePhoto(for: asset, targetSize: view.frame.size, contentMode: .aspectFit, options: options) { (livePhoto, info) in
guard livePhoto != nil else {return}
self.livePhotoImageView.livePhoto = livePhoto
}
這里使用的是PHImageManager,可以通過該類獲取 PHLivePhoto對(duì)象卦溢。
寫了這么多糊余,只是從相冊(cè)中獲取了Live Photo,然后將其展示单寂。那如何獲取該Live Photo的源文件呢啄刹?很簡(jiǎn)單,直接看下面代碼:
@objc func getSourceAction() {
let arr = PHAssetResource.assetResources(for: asset)
let manager = PHAssetResourceManager.default()
let resourceReqOptions = PHAssetResourceRequestOptions.init()
manager.requestData(for: arr[0], options: resourceReqOptions, dataReceivedHandler: { (data) in
let image = UIImage.init(data: data, scale: 1)
print(image ?? "沒有圖片")
}) { (error) in
print(error?.localizedDescription ?? "err")
}
print(arr)
}
這是點(diǎn)擊獲取資源觸發(fā)的Action操作凄贩,主要用到了PHAssetResource和PHAssetResourceManager。
PHAssetResource是于照片庫(kù)中的圖片視頻或者Live Photo 相關(guān)連的底層數(shù)據(jù)資源袱讹,也就是說我可以通過此類獲取Live Photo的圖片+視頻:
通過PHAsset獲取asset 資源數(shù)組疲扎,對(duì)Live Photo而言,數(shù)組包含了圖片+視頻捷雕。這樣如果用戶是通過iOS設(shè)備上傳Live Photo椒丧,開發(fā)者可以獲取到視頻和圖片分別上傳。然后其他端通過使用圖片+視頻模擬Live Photo的展示救巷。
還有一個(gè)問題壶熏,如果是iOS設(shè)備上,如何將網(wǎng)絡(luò)獲取的圖片+視頻展示位Live Photo呢浦译?
既然Apple提供了API讓開發(fā)者獲取Live Photo的原始資源棒假,也可以通過原始資源合成Live Photo:
open class func request(withResourceFileURLs fileURLs: [URL], placeholderImage image: UIImage?, targetSize: CGSize, contentMode: PHImageContentMode, resultHandler: @escaping (PHLivePhoto?, [AnyHashable : Any]) -> Swift.Void) -> PHLivePhotoRequestID
此方法是PHLivePhoto的類方法,作用是根據(jù)提供的資源文件異步合成Live Photo精盅。這個(gè)方法中的URL為一個(gè)數(shù)組帽哑,內(nèi)容為使用Photos庫(kù)導(dǎo)出的Live Photo的源文件(HEIC+mov)。
將生成的Live Photo保存到本地
直接看代碼:
PHPhotoLibrary.shared().performChanges({
let request = PHAssetCreationRequest.forAsset()
let options = PHAssetResourceCreationOptions.init()
let imageUrl = Bundle.main.path(forResource: "livephoto1", ofType: "HEIC")!
let vidoUrl = Bundle.main.path(forResource: "livephoto1", ofType: "mov")!
request.addResource(with: .pairedVideo, fileURL: URL.init(fileURLWithPath: vidoUrl), options: options)
request.addResource(with: .photo, fileURL: URL.init(fileURLWithPath: imageUrl), options: options)
}) { (boo, error) in
if boo {
print("保存到手機(jī)成功")
}else {
print(error?.localizedDescription ?? "error")
}
}
這里主要使用的是PHAssetCreationRequest類叹俏。這里要注意一點(diǎn)妻枕,那就是LivePhoto的視頻添加時(shí), PHAssetResourceType為pairedVideo,這種類型是提供Live Photo原始視頻數(shù)據(jù)的格式屡谐。通過add操作之后述么,可以將合成的Live Photo保存到手機(jī)中。
按照上述的方式愕掏,便可以在iOS平臺(tái)上面去使用Live Photo度秘。
Android
Android本身不支持Live Photo,但是可以進(jìn)行模擬亭珍。先從服務(wù)端拉取要展示的圖片+視頻敷钾,展示時(shí),直接將圖片覆蓋到視頻上肄梨,當(dāng)進(jìn)行按壓時(shí)阻荒,隱藏圖片,播放視頻即可众羡。
Web
Apple為了做在線播放Live Photo侨赡,官方開發(fā)了一套LivePhotoKit的js,通過該JS粱侣,開發(fā)者可以很容易地將圖片+視頻合稱為L(zhǎng)ive Photo展示到網(wǎng)頁(yè)中羊壹。這里是Apple官方提供的Demo。自己有按照LivePhotoKit的指南去開發(fā)齐婴,但是發(fā)現(xiàn)兼容性并不是很好油猫,在Safari中展示沒有什么問題,但是在Chrome和Firefox上展示提示播放失敗柠偶。這里后續(xù)有待進(jìn)一步研究情妖。另外,在Web展示的時(shí)候如果你使用的外鏈圖片和視頻诱担,容易產(chǎn)生跨域問題:
No 'Access-Control-Allow-Origin' header
所以最好通過自己在本地起一個(gè)服務(wù)毡证,然后同源進(jìn)行操作。具體的LivePhotoKit使用可以直接查看官方網(wǎng)站的使用蔫仙。
結(jié)束
LivePhoto本質(zhì)上就是圖片+視頻生成的一種新的照片格式料睛。在對(duì)其進(jìn)行操作的過程中主要用到的Photos+PhotosUI。
代碼Demo可參見這里摇邦。
如有什么疑問恤煞,可留言咨詢!
參考鏈接
1.LivePhotosKit JS
2.Example app using Photos framework
3.Live Photo Editing and RAW Processing with Core Image
4.Working with HEIF and HEVC
5.PHAssetResourceManager usage?
6.拍攝和編輯livephoto
7.FLLivePhotoDemo
8.Live Photo存儲(chǔ)與應(yīng)用
9.iOS開發(fā)創(chuàng)建合成一張LivePhoto