HXPhotoModel.m 97 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106
  1. //
  2. // HXPhotoModel.m
  3. // HXPhotoPickerExample
  4. //
  5. // Created by Silence on 17/2/8.
  6. // Copyright © 2017年 Silence. All rights reserved.
  7. //
  8. #import "HXPhotoModel.h"
  9. #import "HXPhotoTools.h"
  10. #import "HXPhotoManager.h"
  11. #import "UIImage+HXExtension.h"
  12. #import <MediaPlayer/MediaPlayer.h>
  13. #import "HXPhotoCommon.h"
  14. #if __has_include(<SDWebImage/UIImageView+WebCache.h>)
  15. #import <SDWebImage/UIImageView+WebCache.h>
  16. #import <SDWebImage/SDWebImageManager.h>
  17. #import <SDWebImage/SDImageCache.h>
  18. #elif __has_include("UIImageView+WebCache.h")
  19. #import "UIImageView+WebCache.h"
  20. #import "SDWebImageManager.h"
  21. #import "SDImageCache.h"
  22. #endif
  23. #if __has_include(<YYWebImage/YYWebImage.h>)
  24. #import <YYWebImage/YYWebImage.h>
  25. #elif __has_include("YYWebImage.h")
  26. #import "YYWebImage.h"
  27. #elif __has_include(<YYKit/YYKit.h>)
  28. #import <YYKit/YYKit.h>
  29. #elif __has_include("YYKit.h")
  30. #import "YYKit.h"
  31. #endif
  32. #import "HXMECancelBlock.h"
  33. #import "HXPhotoEdit.h"
  34. #import "HXAssetManager.h"
  35. #import "PHAsset+HXExtension.h"
  36. #import "HXPickerResult.h"
  37. @implementation HXPhotoModel
  38. - (void)setSelectIndexStr:(NSString *)selectIndexStr {
  39. _selectIndexStr = selectIndexStr;
  40. self.selectedIndex = selectIndexStr.integerValue - 1;
  41. }
  42. - (NSUInteger)assetByte {
  43. if (_assetByte > 0) {
  44. return _assetByte;
  45. }
  46. NSUInteger byte = 0;
  47. if (self.photoEdit) {
  48. NSData *imageData = HX_UIImagePNGRepresentation(self.photoEdit.editPreviewImage);
  49. if (!imageData) {
  50. imageData = HX_UIImageJPEGRepresentation(self.photoEdit.editPreviewImage);
  51. }
  52. byte = imageData.length;
  53. _assetByte = byte;
  54. return _assetByte;
  55. }
  56. if (self.asset) {
  57. if (self.type == HXPhotoModelMediaTypeLivePhoto) {
  58. NSArray *resources = [PHAssetResource assetResourcesForAsset:self.asset];
  59. for (PHAssetResource *resource in resources) {
  60. if ([resource respondsToSelector:@selector(fileSize)]) {
  61. id fileSize = [resource valueForKey:@"fileSize"];
  62. if (fileSize && ![fileSize isKindOfClass:[NSNull class]]) {
  63. byte += [fileSize unsignedIntegerValue];
  64. }
  65. }
  66. }
  67. }else {
  68. PHAssetResource *resource = [[PHAssetResource assetResourcesForAsset:self.asset] firstObject];
  69. if ([resource respondsToSelector:@selector(fileSize)]) {
  70. id fileSize = [resource valueForKey:@"fileSize"];
  71. if (fileSize && ![fileSize isKindOfClass:[NSNull class]]) {
  72. byte = [fileSize unsignedIntegerValue];
  73. }
  74. }
  75. }
  76. }else {
  77. if (self.type == HXPhotoModelMediaTypeCameraPhoto) {
  78. if (self.networkPhotoUrl || self.networkThumbURL) {
  79. byte = 0;
  80. }else {
  81. NSData *imageData = HX_UIImagePNGRepresentation(self.photoEdit.editPreviewImage);
  82. if (!imageData) {
  83. imageData = HX_UIImageJPEGRepresentation(self.photoEdit.editPreviewImage);
  84. }
  85. // if (UIImagePNGRepresentation(self.thumbPhoto)) {
  86. // //返回为png图像。
  87. // imageData = UIImagePNGRepresentation(self.thumbPhoto);
  88. // }else {
  89. // //返回为JPEG图像。
  90. // imageData = UIImageJPEGRepresentation(self.thumbPhoto, 0.7);
  91. // }
  92. byte = imageData.length;
  93. }
  94. }else if (self.type == HXPhotoModelMediaTypeCameraVideo) {
  95. if (self.cameraVideoType == HXPhotoModelMediaTypeCameraVideoTypeNetWork) {
  96. byte = 0;
  97. }else {
  98. AVURLAsset* urlAsset = [AVURLAsset assetWithURL:self.videoURL];
  99. NSNumber *size;
  100. [urlAsset.URL getResourceValue:&size forKey:NSURLFileSizeKey error:nil];
  101. byte = size.unsignedIntegerValue;
  102. }
  103. }
  104. }
  105. return byte;
  106. }
  107. - (HXPhotoModelFormat)photoFormat {
  108. if (self.subType == HXPhotoModelMediaSubTypePhoto) {
  109. if (self.photoEdit) {
  110. return HXPhotoModelFormatJPG;
  111. }
  112. if (self.asset) {
  113. if (self.type == HXPhotoModelMediaTypePhotoGif) {
  114. return HXPhotoModelFormatGIF;
  115. }
  116. if ([[self.asset valueForKey:@"filename"] hasSuffix:@"PNG"]) {
  117. return HXPhotoModelFormatPNG;
  118. }
  119. if ([[self.asset valueForKey:@"filename"] hasSuffix:@"JPG"]) {
  120. return HXPhotoModelFormatJPG;
  121. }
  122. if ([[self.asset valueForKey:@"filename"] hasSuffix:@"HEIC"]) {
  123. return HXPhotoModelFormatHEIC;
  124. }
  125. if ([[self.asset valueForKey:@"filename"] hasSuffix:@"GIF"]) {
  126. return HXPhotoModelFormatGIF;
  127. }
  128. }else {
  129. if (self.cameraPhotoType == HXPhotoModelMediaTypeCameraPhotoTypeLocalGif ||
  130. self.cameraPhotoType == HXPhotoModelMediaTypeCameraPhotoTypeNetWorkGif) {
  131. return HXPhotoModelFormatGIF;
  132. }
  133. if (self.thumbPhoto) {
  134. if (UIImagePNGRepresentation(self.thumbPhoto)) {
  135. return HXPhotoModelFormatPNG;
  136. }else {
  137. return HXPhotoModelFormatJPG;
  138. }
  139. }
  140. if (self.networkPhotoUrl) {
  141. if ([[self.networkPhotoUrl.absoluteString lowercaseString] hasSuffix:@"png"]) {
  142. return HXPhotoModelFormatPNG;
  143. }
  144. if ([[self.networkPhotoUrl.absoluteString lowercaseString] hasSuffix:@"jpg"]) {
  145. return HXPhotoModelFormatJPG;
  146. }
  147. if ([[self.networkPhotoUrl.absoluteString lowercaseString] hasSuffix:@"gif"]) {
  148. return HXPhotoModelFormatGIF;
  149. }
  150. }
  151. }
  152. }
  153. return HXPhotoModelFormatUnknown;
  154. }
  155. - (BOOL)isEqualToPhotoModel:(HXPhotoModel *)photoModel {
  156. if (!photoModel) {
  157. return NO;
  158. }
  159. if (self == photoModel ){
  160. return YES;
  161. }
  162. if (self.localIdentifier &&
  163. photoModel.localIdentifier &&
  164. [self.localIdentifier isEqualToString:photoModel.localIdentifier]) {
  165. return YES;
  166. }
  167. if (self.thumbPhoto && photoModel.thumbPhoto &&
  168. self.thumbPhoto == photoModel.thumbPhoto) {
  169. return YES;
  170. }
  171. if (self.previewPhoto && photoModel.previewPhoto &&
  172. self.previewPhoto == photoModel.previewPhoto) {
  173. return YES;
  174. }
  175. if (self.thumbPhoto && photoModel.previewPhoto &&
  176. self.thumbPhoto == photoModel.previewPhoto) {
  177. return YES;
  178. }
  179. if (self.previewPhoto && photoModel.thumbPhoto &&
  180. self.previewPhoto == photoModel.thumbPhoto) {
  181. return YES;
  182. }
  183. if (self.videoURL && photoModel.videoURL &&
  184. [self.videoURL.absoluteString isEqualToString:photoModel.videoURL.absoluteString]) {
  185. return YES;
  186. }
  187. if (self.networkPhotoUrl && photoModel.networkPhotoUrl &&
  188. [self.networkPhotoUrl.absoluteString isEqualToString:photoModel.networkPhotoUrl.absoluteString]) {
  189. return YES;
  190. }
  191. if (self.livePhotoVideoURL && photoModel.livePhotoVideoURL &&
  192. [self.livePhotoVideoURL.absoluteString isEqualToString:photoModel.livePhotoVideoURL.absoluteString]) {
  193. return YES;
  194. }
  195. return NO;
  196. }
  197. /// 重写 isEqual 方法 会因为 isEqualToPhotoModel 这个在选择照片的时候导致一点点卡顿所以屏蔽
  198. /// 想要判断两个model是否相容请在需要的时候调用 isEqualToPhotoModel 方法来判断
  199. //- (BOOL)isEqual:(id)object {
  200. // if (self == object) {
  201. // return YES;
  202. // }
  203. // if (![self isKindOfClass:[HXPhotoModel class]]) {
  204. // return NO;
  205. // }
  206. // return [self isEqualToPhotoModel:object];
  207. //}
  208. - (NSDate *)creationDate {
  209. if (self.type == HXPhotoModelMediaTypeCameraPhoto || self.type == HXPhotoModelMediaTypeCameraVideo) {
  210. return _creationDate ?: [NSDate date];
  211. }
  212. if (self.asset) {
  213. return [self.asset valueForKey:@"creationDate"];
  214. }
  215. return _creationDate;
  216. }
  217. - (NSDate *)modificationDate {
  218. if (self.type == HXPhotoModelMediaTypeCameraPhoto || self.type == HXPhotoModelMediaTypeCameraVideo) {
  219. return [NSDate date];
  220. }
  221. return [self.asset valueForKey:@"modificationDate"];
  222. }
  223. - (CLLocation *)location {
  224. if (self.asset) {
  225. return [self.asset valueForKey:@"location"];
  226. }
  227. return _location;
  228. }
  229. - (NSString *)localIdentifier {
  230. if (self.asset) {
  231. return self.asset.localIdentifier;
  232. }
  233. return _localIdentifier;
  234. }
  235. - (NSTimeInterval)videoDuration {
  236. if (!_videoDuration) {
  237. if (self.asset) {
  238. return self.asset.duration;
  239. }
  240. }
  241. return _videoDuration;
  242. }
  243. - (UIImage *)thumbPhoto {
  244. if (self.photoEdit) {
  245. return self.photoEdit.editPreviewImage;
  246. }
  247. return _thumbPhoto;
  248. }
  249. - (UIImage *)previewPhoto {
  250. if (self.photoEdit) {
  251. return self.photoEdit.editPreviewImage;
  252. }
  253. return _previewPhoto;
  254. }
  255. + (instancetype)photoModelWithPHAsset:(PHAsset *)asset {
  256. return [[self alloc] initWithPHAsset:asset];
  257. }
  258. + (instancetype)videoCoverWithPHAsset:(PHAsset *)asset {
  259. return [[self alloc] initVideoCoverWithPHAsset:asset];
  260. }
  261. + (instancetype)photoModelWithImage:(UIImage *)image {
  262. return [[self alloc] initWithImage:image];
  263. }
  264. + (instancetype)photoModelWithImageURL:(NSURL *)imageURL {
  265. return [[self alloc] initWithImageURL:imageURL thumbURL:imageURL];
  266. }
  267. + (instancetype)photoModelWithVideoURL:(NSURL *)videoURL videoTime:(NSTimeInterval)videoTime {
  268. return [[self alloc] initWithVideoURL:videoURL videoTime:videoTime];
  269. }
  270. + (instancetype)photoModelWithVideoURL:(NSURL *)videoURL {
  271. return [[self alloc] initWithVideoURL:videoURL];
  272. }
  273. + (instancetype)photoModelWithImageURL:(NSURL *)imageURL thumbURL:(NSURL *)thumbURL {
  274. return [[self alloc] initWithImageURL:imageURL thumbURL:thumbURL];
  275. }
  276. + (instancetype)photoModelWithNetworkVideoURL:(NSURL *)videoURL videoCoverURL:(NSURL *)videoCoverURL videoDuration:(NSTimeInterval)videoDuration {
  277. return [[self alloc] initWithNetworkVideoURL:videoURL videoCoverURL:videoCoverURL videoDuration:videoDuration];
  278. }
  279. + (instancetype _Nullable)photoModelWithLivePhotoImage:(UIImage * _Nullable)image
  280. videoURL:(NSURL * _Nullable)videoURL {
  281. return [[self alloc] initLivePhotoWithImage:image videoURL:videoURL];
  282. }
  283. + (instancetype _Nullable)photoModelWithLivePhotoNetWorkImage:(NSURL * _Nullable)imageURL
  284. netWorkVideoURL:(NSURL * _Nullable)videoURL {
  285. return [[self alloc] initLivePhotoModelWithNetWorkImage:imageURL netWorkVideoURL:videoURL];
  286. }
  287. - (instancetype _Nullable)initLivePhotoModelWithNetWorkImage:(NSURL * _Nullable)imageURL
  288. netWorkVideoURL:(NSURL * _Nullable)videoURL {
  289. if (self = [super init]) {
  290. self.type = HXPhotoModelMediaTypeCameraPhoto;
  291. self.subType = HXPhotoModelMediaSubTypePhoto;
  292. self.cameraPhotoType = HXPhotoModelMediaTypeCameraPhotoTypeNetWorkLivePhoto;
  293. self.networkPhotoUrl = imageURL;
  294. self.networkThumbURL = imageURL;
  295. self.livePhotoVideoURL = videoURL;
  296. self.loadOriginalImage = YES;
  297. self.thumbPhoto = [UIImage hx_imageNamed:@"hx_qz_photolist_picture_fail"];
  298. self.previewPhoto = self.thumbPhoto;
  299. self.imageSize = self.thumbPhoto.size;
  300. }
  301. return self;
  302. }
  303. - (instancetype)initLivePhotoWithImage:(UIImage * _Nullable)image
  304. videoURL:(NSURL * _Nullable)videoURL {
  305. if (self = [super init]) {
  306. self.type = HXPhotoModelMediaTypeCameraPhoto;
  307. self.subType = HXPhotoModelMediaSubTypePhoto;
  308. self.cameraPhotoType = HXPhotoModelMediaTypeCameraPhotoTypeLocalLivePhoto;
  309. self.thumbPhoto = image;
  310. self.previewPhoto = image;
  311. self.videoURL = videoURL;
  312. self.imageSize = self.thumbPhoto.size;
  313. }
  314. return self;
  315. }
  316. - (instancetype)initWithNetworkVideoURL:(NSURL *)videoURL videoCoverURL:(NSURL *)videoCoverURL videoDuration:(NSTimeInterval)videoDuration {
  317. if (self = [super init]) {
  318. self.type = HXPhotoModelMediaTypeCameraVideo;
  319. self.subType = HXPhotoModelMediaSubTypeVideo;
  320. self.cameraVideoType = HXPhotoModelMediaTypeCameraVideoTypeNetWork;
  321. if (videoDuration <= 0) {
  322. videoDuration = 1;
  323. }
  324. NSString *time = [HXPhotoTools transformVideoTimeToString:videoDuration];
  325. self.videoDuration = videoDuration;
  326. self.videoURL = videoURL;
  327. self.videoTime = time;
  328. self.thumbPhoto = [UIImage hx_imageNamed:@"hx_qz_photolist_picture_fail"];
  329. self.previewPhoto = self.thumbPhoto;
  330. self.imageSize = self.thumbPhoto.size;
  331. self.networkPhotoUrl = videoCoverURL;
  332. self.networkThumbURL = videoCoverURL;
  333. self.loadOriginalImage = YES;
  334. }
  335. return self;
  336. }
  337. - (instancetype)initWithImageURL:(NSURL *)imageURL thumbURL:(NSURL *)thumbURL {
  338. if (self = [super init]) {
  339. self.type = HXPhotoModelMediaTypeCameraPhoto;
  340. self.subType = HXPhotoModelMediaSubTypePhoto;
  341. self.thumbPhoto = [UIImage hx_imageNamed:@"hx_qz_photolist_picture_fail"];
  342. self.previewPhoto = self.thumbPhoto;
  343. self.imageSize = self.thumbPhoto.size;
  344. if (!imageURL && thumbURL) {
  345. imageURL = thumbURL;
  346. }else if (imageURL && !thumbURL) {
  347. thumbURL = imageURL;
  348. }
  349. self.networkPhotoUrl = imageURL;
  350. self.networkThumbURL = thumbURL;
  351. if (imageURL.absoluteString.length > 3 && [[imageURL.absoluteString substringFromIndex:imageURL.absoluteString.length - 3] isEqualToString:@"gif"]) {
  352. self.cameraPhotoType = HXPhotoModelMediaTypeCameraPhotoTypeNetWorkGif;
  353. }else {
  354. self.cameraPhotoType = HXPhotoModelMediaTypeCameraPhotoTypeNetWork;
  355. }
  356. if (imageURL == thumbURL ||
  357. [imageURL.absoluteString isEqualToString:thumbURL.absoluteString]) {
  358. self.loadOriginalImage = YES;
  359. }
  360. }
  361. return self;
  362. }
  363. - (instancetype)initWithPHAsset:(PHAsset *)asset {
  364. if (self = [super init]) {
  365. if (asset.mediaType == PHAssetMediaTypeImage) {
  366. self.subType = HXPhotoModelMediaSubTypePhoto;
  367. self.type = HXPhotoModelMediaTypePhoto;
  368. }else if (asset.mediaType == PHAssetMediaTypeVideo) {
  369. self.subType = HXPhotoModelMediaSubTypeVideo;
  370. self.type = HXPhotoModelMediaTypeVideo;
  371. self.videoDuration = [[NSString stringWithFormat:@"%.0f",asset.duration] floatValue];
  372. NSString *time = [HXPhotoTools transformVideoTimeToString:self.videoDuration];
  373. self.videoTime = time;
  374. }
  375. self.asset = asset;
  376. }
  377. return self;
  378. }
  379. - (instancetype)initVideoCoverWithPHAsset:(PHAsset *)asset {
  380. if (self = [super init]) {
  381. self.subType = HXPhotoModelMediaSubTypePhoto;
  382. self.type = HXPhotoModelMediaTypePhoto;
  383. self.asset = asset;
  384. }
  385. return self;
  386. }
  387. - (instancetype)initWithVideoURL:(NSURL *)videoURL {
  388. NSDictionary *opts = [NSDictionary dictionaryWithObject:[NSNumber numberWithBool:NO]
  389. forKey:AVURLAssetPreferPreciseDurationAndTimingKey];
  390. AVURLAsset *urlAsset = [AVURLAsset URLAssetWithURL:videoURL options:opts];
  391. return [self initWithVideoURL:videoURL videoTime:CMTimeGetSeconds(urlAsset.duration)];
  392. }
  393. - (instancetype)initWithVideoURL:(NSURL *)videoURL videoTime:(NSTimeInterval)videoTime {
  394. if (self = [super init]) {
  395. self.type = HXPhotoModelMediaTypeCameraVideo;
  396. self.subType = HXPhotoModelMediaSubTypeVideo;
  397. self.cameraVideoType = HXPhotoModelMediaTypeCameraVideoTypeLocal;
  398. self.videoURL = videoURL;
  399. if (videoTime <= 0) {
  400. videoTime = 1;
  401. }
  402. UIImage *image = [UIImage hx_thumbnailImageForVideo:videoURL atTime:0.1f];
  403. NSString *time = [HXPhotoTools transformVideoTimeToString:videoTime];
  404. self.videoDuration = videoTime;
  405. self.videoURL = videoURL;
  406. self.videoTime = time;
  407. self.thumbPhoto = image;
  408. self.previewPhoto = image;
  409. self.imageSize = self.thumbPhoto.size;
  410. }
  411. return self;
  412. }
  413. - (instancetype)initWithImage:(UIImage *)image {
  414. self = [super init];
  415. if (self) {
  416. self.type = HXPhotoModelMediaTypeCameraPhoto;
  417. if (image.images.count) {
  418. self.cameraPhotoType = HXPhotoModelMediaTypeCameraPhotoTypeLocalGif;
  419. }else {
  420. self.cameraPhotoType = HXPhotoModelMediaTypeCameraPhotoTypeLocal;
  421. }
  422. self.subType = HXPhotoModelMediaSubTypePhoto;
  423. if (image.imageOrientation != UIImageOrientationUp) {
  424. image = [image hx_normalizedImage];
  425. }
  426. self.thumbPhoto = image;
  427. self.previewPhoto = image;
  428. self.imageSize = image.size;
  429. }
  430. return self;
  431. }
  432. - (void)setPhotoEdit:(HXPhotoEdit *)photoEdit {
  433. _photoEdit = photoEdit;
  434. if (!photoEdit) {
  435. _imageSize = CGSizeZero;
  436. }
  437. }
  438. - (CGSize)imageSize {
  439. if (self.photoEdit) {
  440. _imageSize = self.photoEdit.editPreviewImage.size;
  441. }
  442. if (_imageSize.width == 0 || _imageSize.height == 0) {
  443. if (self.asset) {
  444. if (self.asset.pixelWidth == 0 || self.asset.pixelHeight == 0) {
  445. _imageSize = CGSizeMake(200, 200);
  446. }else {
  447. _imageSize = CGSizeMake(self.asset.pixelWidth, self.asset.pixelHeight);
  448. }
  449. }else {
  450. if (CGSizeEqualToSize(self.thumbPhoto.size, CGSizeZero)) {
  451. _imageSize = CGSizeMake(200, 200);
  452. }else {
  453. _imageSize = self.thumbPhoto.size;
  454. }
  455. }
  456. }
  457. return _imageSize;
  458. }
  459. - (NSString *)videoTime {
  460. if (!_videoTime) {
  461. _videoTime = [HXPhotoTools transformVideoTimeToString:self.videoDuration];
  462. }
  463. return _videoTime;
  464. }
  465. - (CGSize)endImageSize
  466. {
  467. if (_endImageSize.width == 0 || _endImageSize.height == 0) {
  468. CGFloat width = [UIScreen mainScreen].bounds.size.width;
  469. CGFloat height = [UIScreen mainScreen].bounds.size.height;
  470. CGFloat imgWidth = self.imageSize.width;
  471. CGFloat imgHeight = self.imageSize.height;
  472. CGFloat w;
  473. CGFloat h;
  474. NSThread *thread = [NSThread currentThread];
  475. UIInterfaceOrientation orientation = UIInterfaceOrientationPortrait;
  476. if (thread.isMainThread) {
  477. orientation = [[UIApplication sharedApplication] statusBarOrientation];
  478. }
  479. if ((orientation == UIInterfaceOrientationLandscapeRight || orientation == UIInterfaceOrientationLandscapeLeft) && !HX_UI_IS_IPAD) {
  480. w = height / self.imageSize.height * imgWidth;
  481. h = height;
  482. }else {
  483. imgHeight = width / imgWidth * imgHeight;
  484. w = width;
  485. h = imgHeight;
  486. }
  487. _endImageSize = CGSizeMake(w, h);
  488. }
  489. return _endImageSize;
  490. }
  491. - (CGSize)previewViewSize {
  492. if (_previewViewSize.width == 0 || _previewViewSize.height == 0) {
  493. _previewViewSize = self.endImageSize;
  494. CGFloat height = [UIScreen mainScreen].bounds.size.height;
  495. if ([HXPhotoCommon photoCommon].isHapticTouch) {
  496. if (_previewViewSize.height > height * 0.6f) {
  497. _previewViewSize.height = height * 0.6f;
  498. }
  499. }else {
  500. if (_previewViewSize.height > height + 20) {
  501. _previewViewSize.height = height;
  502. }
  503. }
  504. }
  505. return _previewViewSize;
  506. }
  507. - (CGSize)dateBottomImageSize {
  508. if (_dateBottomImageSize.width == 0 || _dateBottomImageSize.height == 0) {
  509. CGFloat width = 0;
  510. CGFloat height = 50;
  511. CGFloat imgWidth = self.imageSize.width;
  512. CGFloat imgHeight = self.imageSize.height;
  513. if (imgHeight > height) {
  514. width = imgWidth * (height / imgHeight);
  515. }else {
  516. width = imgWidth * (imgHeight / height);
  517. }
  518. if (width < 50 / 16 * 9) {
  519. width = 50 / 16 * 9;
  520. }
  521. _dateBottomImageSize = CGSizeMake(width, height);
  522. }
  523. return _dateBottomImageSize;
  524. }
  525. - (NSString *)barTitle {
  526. if (!_barTitle) {
  527. if ([self.creationDate hx_isToday]) {
  528. _barTitle = [NSBundle hx_localizedStringForKey:@"今天"];
  529. }else if ([self.creationDate hx_isYesterday]) {
  530. _barTitle = [NSBundle hx_localizedStringForKey:@"昨天"];
  531. }else if ([self.creationDate hx_isSameWeek]) {
  532. _barTitle = [self.creationDate hx_getNowWeekday];
  533. }else if ([self.creationDate hx_isThisYear]) {
  534. HXPhotoLanguageType type = [HXPhotoCommon photoCommon].languageType;
  535. switch (type) {
  536. case HXPhotoLanguageTypeSc :
  537. case HXPhotoLanguageTypeTc :
  538. case HXPhotoLanguageTypeJa : {
  539. // 中 / 日 / 繁
  540. _barTitle = [NSString stringWithFormat:@"%@ %@",[self.creationDate hx_dateStringWithFormat:@"MM月dd日"],[self.creationDate hx_getNowWeekday]];
  541. } break;
  542. case HXPhotoLanguageTypeKo : {
  543. // 韩语
  544. _barTitle = [NSString stringWithFormat:@"%@ %@",[self.creationDate hx_dateStringWithFormat:@"MM월dd일"],[self.creationDate hx_getNowWeekday]];
  545. } break;
  546. case HXPhotoLanguageTypeEn : {
  547. // 英文
  548. _barTitle = [NSString stringWithFormat:@"%@ %@",[self.creationDate hx_dateStringWithFormat:@"MMM dd"],[self.creationDate hx_getNowWeekday]];
  549. } break;
  550. default : {
  551. NSString *language = [NSLocale preferredLanguages].firstObject;
  552. if ([language hasPrefix:@"zh"] ||
  553. [language hasPrefix:@"ja"]) {
  554. // 中 / 日 / 繁
  555. _barTitle = [NSString stringWithFormat:@"%@ %@",[self.creationDate hx_dateStringWithFormat:@"MM月dd日"],[self.creationDate hx_getNowWeekday]];
  556. }else if ([language hasPrefix:@"ko"]) {
  557. // 韩语
  558. _barTitle = [NSString stringWithFormat:@"%@ %@",[self.creationDate hx_dateStringWithFormat:@"MM월dd일"],[self.creationDate hx_getNowWeekday]];
  559. } else {
  560. // 英文
  561. _barTitle = [NSString stringWithFormat:@"%@ %@",[self.creationDate hx_dateStringWithFormat:@"MMM dd"],[self.creationDate hx_getNowWeekday]];
  562. }
  563. }break;
  564. }
  565. }else {
  566. HXPhotoLanguageType type = [HXPhotoCommon photoCommon].languageType;
  567. switch (type) {
  568. case HXPhotoLanguageTypeSc :
  569. case HXPhotoLanguageTypeTc :
  570. case HXPhotoLanguageTypeJa : {
  571. // 中 / 日 / 繁
  572. _barTitle = [self.creationDate hx_dateStringWithFormat:@"yyyy年MM月dd日"];
  573. } break;
  574. case HXPhotoLanguageTypeKo : {
  575. // 韩语
  576. _barTitle = [self.creationDate hx_dateStringWithFormat:@"yyyy년MM월dd일"];
  577. } break;
  578. case HXPhotoLanguageTypeEn : {
  579. // 英文
  580. _barTitle = [self.creationDate hx_dateStringWithFormat:@"MMM dd, yyyy"];
  581. } break;
  582. default : {
  583. NSString *language = [NSLocale preferredLanguages].firstObject;
  584. if ([language hasPrefix:@"zh"] ||
  585. [language hasPrefix:@"ja"]) {
  586. // 中 / 日 / 繁
  587. _barTitle = [self.creationDate hx_dateStringWithFormat:@"yyyy年MM月dd日"];
  588. }else if ([language hasPrefix:@"ko"]) {
  589. // 韩语
  590. _barTitle = [self.creationDate hx_dateStringWithFormat:@"yyyy년MM월dd일"];
  591. } else {
  592. // 英文
  593. _barTitle = [self.creationDate hx_dateStringWithFormat:@"MMM dd, yyyy"];
  594. }
  595. }break;
  596. }
  597. }
  598. }
  599. return _barTitle;
  600. }
  601. - (NSString *)barSubTitle {
  602. if (!_barSubTitle) {
  603. _barSubTitle = [self.creationDate hx_dateStringWithFormat:@"HH:mm"];
  604. }
  605. return _barSubTitle;
  606. }
  607. - (void)isICloudAssetWithCompletion:(void (^)(BOOL isICloud, HXPhotoModel *model))completion {
  608. if (!self.asset) {
  609. if (completion) {
  610. completion(NO, self);
  611. }
  612. }
  613. dispatch_async(dispatch_get_global_queue(0, 0), ^{
  614. NSArray *resourceArray = [PHAssetResource assetResourcesForAsset:self.asset];
  615. BOOL bIsLocallayAvailable = [[resourceArray.firstObject valueForKey:@"locallyAvailable"] boolValue];
  616. if (completion) {
  617. dispatch_async(dispatch_get_main_queue(), ^{
  618. completion(!bIsLocallayAvailable, self);
  619. });
  620. }
  621. });
  622. }
  623. - (void)dealloc {
  624. if (self.iCloudRequestID) {
  625. if (self.iCloudDownloading) {
  626. [[PHImageManager defaultManager] cancelImageRequest:self.iCloudRequestID];
  627. }
  628. }
  629. // [self cancelImageRequest];
  630. }
  631. - (instancetype)initWithCoder:(NSCoder *)aDecoder {
  632. if (self = [super init]) {
  633. self.type = [aDecoder decodeIntegerForKey:@"type"];
  634. self.subType = [aDecoder decodeIntegerForKey:@"subType"];
  635. if (self.type == HXPhotoModelMediaTypeCameraPhoto ||
  636. self.type == HXPhotoModelMediaTypeCameraVideo) {
  637. self.thumbPhoto = [aDecoder decodeObjectForKey:@"thumbPhoto"];
  638. self.previewPhoto = [aDecoder decodeObjectForKey:@"previewPhoto"];
  639. }
  640. self.localIdentifier = [aDecoder decodeObjectForKey:@"localIdentifier"];
  641. self.videoDuration = [aDecoder decodeFloatForKey:@"videoDuration"];
  642. self.selected = [aDecoder decodeBoolForKey:@"selected"];
  643. self.videoURL = [aDecoder decodeObjectForKey:@"videoURL"];
  644. self.imageURL = [aDecoder decodeObjectForKey:@"imageURL"];
  645. self.livePhotoVideoURL = [aDecoder decodeObjectForKey:@"livePhotoVideoURL"];
  646. self.networkPhotoUrl = [aDecoder decodeObjectForKey:@"networkPhotoUrl"];
  647. self.networkThumbURL = [aDecoder decodeObjectForKey:@"networkThumbURL"];
  648. self.creationDate = [aDecoder decodeObjectForKey:@"creationDate"];
  649. self.modificationDate = [aDecoder decodeObjectForKey:@"modificationDate"];
  650. self.location = [aDecoder decodeObjectForKey:@"location"];
  651. self.videoTime = [aDecoder decodeObjectForKey:@"videoTime"];
  652. self.selectIndexStr = [aDecoder decodeObjectForKey:@"selectIndexStr"];
  653. self.cameraIdentifier = [aDecoder decodeObjectForKey:@"cameraIdentifier"];
  654. self.cameraPhotoType = [aDecoder decodeIntegerForKey:@"cameraPhotoType"];
  655. self.cameraVideoType = [aDecoder decodeIntegerForKey:@"cameraVideoType"];
  656. self.photoEdit = [aDecoder decodeObjectForKey:@"photoEdit"];
  657. }
  658. return self;
  659. }
  660. - (void)encodeWithCoder:(NSCoder *)aCoder {
  661. if (self.type == HXPhotoModelMediaTypeCameraPhoto ||
  662. self.type == HXPhotoModelMediaTypeCameraVideo) {
  663. [aCoder encodeObject:self.thumbPhoto forKey:@"thumbPhoto"];
  664. [aCoder encodeObject:self.previewPhoto forKey:@"previewPhoto"];
  665. }
  666. [aCoder encodeObject:self.localIdentifier forKey:@"localIdentifier"];
  667. [aCoder encodeInteger:self.type forKey:@"type"];
  668. [aCoder encodeInteger:self.subType forKey:@"subType"];
  669. [aCoder encodeInteger:self.cameraPhotoType forKey:@"cameraPhotoType"];
  670. [aCoder encodeInteger:self.cameraVideoType forKey:@"cameraVideoType"];
  671. [aCoder encodeFloat:self.videoDuration forKey:@"videoDuration"];
  672. [aCoder encodeBool:self.selected forKey:@"selected"];
  673. [aCoder encodeObject:self.videoURL forKey:@"videoURL"];
  674. [aCoder encodeObject:self.imageURL forKey:@"imageURL"];
  675. [aCoder encodeObject:self.livePhotoVideoURL forKey:@"livePhotoVideoURL"];
  676. [aCoder encodeObject:self.networkPhotoUrl forKey:@"networkPhotoUrl"];
  677. [aCoder encodeObject:self.networkThumbURL forKey:@"networkThumbURL"];
  678. [aCoder encodeObject:self.creationDate forKey:@"creationDate"];
  679. [aCoder encodeObject:self.modificationDate forKey:@"modificationDate"];
  680. [aCoder encodeObject:self.location forKey:@"location"];
  681. [aCoder encodeObject:self.videoTime forKey:@"videoTime"];
  682. [aCoder encodeObject:self.selectIndexStr forKey:@"selectIndexStr"];
  683. [aCoder encodeObject:self.cameraIdentifier forKey:@"cameraIdentifier"];
  684. [aCoder encodeObject:self.photoEdit forKey:@"photoEdit"];
  685. }
  686. #pragma mark - < Request >
  687. + (id)requestImageWithURL:(NSURL *)url progress:(void (^ _Nullable)(NSInteger, NSInteger))progress completion:(void (^ _Nullable)(UIImage * _Nullable, NSURL * _Nullable, NSError * _Nullable))completion {
  688. #if HasSDWebImage
  689. SDWebImageCombinedOperation *operation = [[SDWebImageManager sharedManager] loadImageWithURL:url options:0 progress:nil completed:^(UIImage * _Nullable image, NSData * _Nullable data, NSError * _Nullable error, SDImageCacheType cacheType, BOOL finished, NSURL * _Nullable imageURL) {
  690. if (completion) {
  691. completion(image, url, error);
  692. }
  693. }];
  694. return operation;
  695. #elif HasYYKitOrWebImage
  696. YYWebImageOperation *operation = [[YYWebImageManager sharedManager] requestImageWithURL:url options:0 progress:progress transform:nil completion:^(UIImage * _Nullable image, NSURL * _Nonnull url, YYWebImageFromType from, YYWebImageStage stage, NSError * _Nullable error) {
  697. if (completion) {
  698. completion(image, url, error);
  699. }
  700. }];
  701. return operation;
  702. #endif
  703. return nil;
  704. }
  705. - (PHImageRequestID)requestThumbImageCompletion:(HXModelImageSuccessBlock)completion {
  706. return [self requestThumbImageWithWidth:[HXPhotoCommon photoCommon].requestWidth completion:completion];
  707. }
  708. - (PHImageRequestID)highQualityRequestThumbImageWithWidth:(CGFloat)width completion:(HXModelImageSuccessBlock)completion {
  709. if (self.photoEdit) {
  710. if (completion) completion(self.photoEdit.editPreviewImage, self, nil);
  711. return 0;
  712. }
  713. return [HXAssetManager requestThumbnailImageForAsset:self.asset targetWidth:width deliveryMode:PHImageRequestOptionsDeliveryModeHighQualityFormat completion:^(UIImage * _Nonnull result, NSDictionary<NSString *,id> * _Nonnull info) {
  714. __strong typeof(self) strongSelf = self;
  715. BOOL downloadFinined = (![[info objectForKey:PHImageCancelledKey] boolValue] && ![info objectForKey:PHImageErrorKey]);
  716. if (downloadFinined && result) {
  717. if (completion) completion(result, strongSelf, info);
  718. }
  719. }];
  720. }
  721. - (PHImageRequestID)requestThumbImageWithWidth:(CGFloat)width completion:(HXModelImageSuccessBlock)completion {
  722. if (self.photoEdit) {
  723. if (completion) completion(self.photoEdit.editPosterImage, self, nil);
  724. return 0;
  725. }
  726. if (self.type == HXPhotoModelMediaTypeCameraPhoto ||
  727. self.type == HXPhotoModelMediaTypeCameraVideo) {
  728. if (!self.networkPhotoUrl) {
  729. if (completion) completion(self.thumbPhoto, self, nil);
  730. }else {
  731. [HXPhotoModel requestImageWithURL:self.networkPhotoUrl progress:nil completion:^(UIImage * _Nullable image, NSURL * _Nonnull url, NSError * _Nullable error) {
  732. __strong typeof(self) strongSelf = self;
  733. if (completion) completion(image, strongSelf, nil);
  734. }];
  735. }
  736. return 0;
  737. }
  738. return [HXAssetManager requestThumbnailImageForAsset:self.asset targetWidth:width completion:^(UIImage * _Nonnull result, NSDictionary<NSString *,id> * _Nonnull info) {
  739. __strong typeof(self) strongSelf = self;
  740. BOOL downloadFinined = (![[info objectForKey:PHImageCancelledKey] boolValue] && ![info objectForKey:PHImageErrorKey]);
  741. if (downloadFinined && result) {
  742. if (completion) completion(result, strongSelf, info);
  743. }
  744. }];
  745. }
  746. - (PHImageRequestID)requestPreviewImageWithSize:(CGSize)size
  747. startRequestICloud:(HXModelStartRequestICloud)startRequestICloud
  748. progressHandler:(HXModelProgressHandler)progressHandler
  749. success:(HXModelImageSuccessBlock)success
  750. failed:(HXModelFailedBlock)failed {
  751. if (self.photoEdit) {
  752. if (success) success(self.photoEdit.editPreviewImage, self, nil);
  753. return 0;
  754. }
  755. if (self.type == HXPhotoModelMediaTypeCameraPhoto ||
  756. self.type == HXPhotoModelMediaTypeCameraVideo) {
  757. if (!self.networkPhotoUrl) {
  758. if (success) success(self.previewPhoto, self, nil);
  759. }else {
  760. if (startRequestICloud) startRequestICloud(0, self);
  761. [HXPhotoModel requestImageWithURL:self.networkPhotoUrl progress:^(NSInteger receivedSize, NSInteger expectedSize) {
  762. __strong typeof(self) strongSelf = self;
  763. dispatch_async(dispatch_get_main_queue(), ^{
  764. if (progressHandler) {
  765. progressHandler((CGFloat)receivedSize / (CGFloat)expectedSize, strongSelf);
  766. }
  767. });
  768. } completion:^(UIImage * _Nullable image, NSURL * _Nonnull url, NSError * _Nullable error) {
  769. __strong typeof(self) strongSelf = self;
  770. dispatch_async(dispatch_get_main_queue(), ^{
  771. if (image) {
  772. if (!strongSelf.thumbPhoto) strongSelf.thumbPhoto = image;
  773. if (!strongSelf.previewPhoto) strongSelf.previewPhoto = image;
  774. if (success) success(image, strongSelf, nil);
  775. }else {
  776. if (failed) failed(nil, strongSelf);
  777. }
  778. });
  779. }];
  780. }
  781. return 0;
  782. }
  783. self.iCloudDownloading = YES;
  784. PHImageRequestID requestId = [HXAssetManager requestPreviewImageForAsset:self.asset targetSize:size networkAccessAllowed:NO progressHandler:nil completion:^(UIImage * _Nonnull result, NSDictionary<NSString *,id> * _Nonnull info) {
  785. __strong typeof(self) strongSelf = self;
  786. [strongSelf requestDataWithResult:result info:info size:size resultClass:[UIImage class] orientation:0 audioMix:nil startRequestICloud:startRequestICloud progressHandler:progressHandler success:^(id result, NSDictionary *info, UIImageOrientation orientation, AVAudioMix *audioMix) {
  787. if (success) {
  788. strongSelf.thumbPhoto = result;
  789. strongSelf.previewPhoto = result;
  790. success(result, strongSelf, info);
  791. }
  792. } failed:failed];
  793. }];
  794. self.iCloudRequestID = requestId;
  795. return requestId;
  796. }
  797. - (PHImageRequestID)requestLivePhotoWithSize:(CGSize)size
  798. startRequestICloud:(HXModelStartRequestICloud)startRequestICloud
  799. progressHandler:(HXModelProgressHandler)progressHandler
  800. success:(HXModelLivePhotoSuccessBlock)success
  801. failed:(HXModelFailedBlock)failed {
  802. PHImageRequestID requestId = 0;
  803. self.iCloudDownloading = YES;
  804. requestId = [HXAssetManager requestPreviewLivePhotoForAsset:self.asset targetSize:size networkAccessAllowed:NO progressHandler:nil completion:^(PHLivePhoto * _Nonnull livePhoto, NSDictionary<NSString *,id> * _Nonnull info) {
  805. __strong typeof(self) strongSelf = self;
  806. [strongSelf requestDataWithResult:livePhoto info:info size:size resultClass:[PHLivePhoto class] orientation:0 audioMix:nil startRequestICloud:startRequestICloud progressHandler:progressHandler success:^(id result, NSDictionary *info, UIImageOrientation orientation, AVAudioMix *audioMix) {
  807. if (success) {
  808. success(result, strongSelf, info);
  809. }
  810. } failed:failed];
  811. }];
  812. self.iCloudRequestID = requestId;
  813. return requestId;
  814. }
  815. - (void)requestLocalLivePhotoWithReqeustID:(void (^)(PHLivePhotoRequestID requestID))requestID
  816. header:(void (^)(AVAssetWriter *, AVAssetReader *, AVAssetReader *))header
  817. completion:(HXModelLivePhotoSuccessBlock)completion {
  818. __block BOOL writeImageSuccess = NO;
  819. __block BOOL writeVideoSuccess = NO;
  820. dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
  821. if (!self.imageURL && !self.videoURL) {
  822. if (completion) {
  823. completion(nil, self, nil);
  824. }
  825. return;
  826. }
  827. NSURL *tempImageURL;
  828. if (!self.imageURL) {
  829. NSString *fileName = [self.videoURL.lastPathComponent.stringByDeletingPathExtension stringByAppendingString:@"_local_img"];
  830. fileName = HXDiskCacheFileNameForKey(fileName, NO);
  831. fileName = [HXPhotoPickerLivePhotoImagesPath stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.jpg", fileName]];
  832. tempImageURL = [NSURL fileURLWithPath:fileName];
  833. }else {
  834. tempImageURL = self.imageURL;
  835. }
  836. BOOL hasVideoURL = [HXPhotoTools fileExistsAtLivePhotoVideoURL:self.videoURL];
  837. BOOL hasImageURL = [HXPhotoTools fileExistsAtLivePhotoImageURL:tempImageURL];
  838. NSURL *toImageURL = [NSURL fileURLWithPath:[NSString stringWithFormat:@"%@.jpg", [HXPhotoTools getLivePhotoImageURLFilePath:tempImageURL]]];
  839. NSURL *toVideoURL = [NSURL fileURLWithPath:[NSString stringWithFormat:@"%@.mov", [HXPhotoTools getLivePhotoVideoURLFilePath:self.videoURL]]];
  840. if (!hasVideoURL || !hasImageURL) {
  841. hasVideoURL = NO;
  842. hasImageURL = NO;
  843. [[NSFileManager defaultManager] removeItemAtURL:toImageURL error:nil];
  844. [[NSFileManager defaultManager] removeItemAtURL:toVideoURL error:nil];
  845. }
  846. HXWeakSelf
  847. if (!hasImageURL) {
  848. if (!self.imageURL) {
  849. if (![[NSFileManager defaultManager] fileExistsAtPath:tempImageURL.path]) {
  850. NSData *imageData = UIImageJPEGRepresentation(self.thumbPhoto, 1);
  851. [imageData writeToURL:tempImageURL atomically:YES];
  852. }
  853. self.imageURL = tempImageURL;
  854. }
  855. [HXPhotoTools writeToFileWithOriginJPGPath:self.imageURL TargetWriteFilePath:toImageURL completion:^(BOOL success) {
  856. writeImageSuccess = YES;
  857. if (writeVideoSuccess) {
  858. dispatch_async(dispatch_get_main_queue(), ^{
  859. if (success) {
  860. PHLivePhotoRequestID requestId = [weakSelf writeAfterCompletionRequestWithCompletion:completion];
  861. if (requestID) {
  862. requestID(requestId);
  863. }
  864. }else {
  865. if (completion) {
  866. completion(nil, weakSelf, nil);
  867. }
  868. }
  869. });
  870. }
  871. }];
  872. }else {
  873. if (!self.imageURL) {
  874. self.imageURL = tempImageURL;
  875. }
  876. writeImageSuccess = YES;
  877. }
  878. if (!hasVideoURL) {
  879. [HXPhotoTools writeToFileWithOriginMovPath:self.videoURL TargetWriteFilePath:toVideoURL header:header completion:^(BOOL success) {
  880. writeVideoSuccess = YES;
  881. if (writeImageSuccess) {
  882. dispatch_async(dispatch_get_main_queue(), ^{
  883. if (success) {
  884. PHLivePhotoRequestID requestId = [weakSelf writeAfterCompletionRequestWithCompletion:completion];
  885. if (requestID) {
  886. requestID(requestId);
  887. }
  888. }else {
  889. if (completion) {
  890. completion(nil, weakSelf, nil);
  891. }
  892. }
  893. });
  894. }
  895. }];
  896. }else {
  897. writeVideoSuccess = YES;
  898. if (writeImageSuccess) {
  899. dispatch_async(dispatch_get_main_queue(), ^{
  900. PHLivePhotoRequestID requestId = [self writeAfterCompletionRequestWithCompletion:completion];
  901. if (requestID) {
  902. requestID(requestId);
  903. }
  904. });
  905. }
  906. }
  907. });
  908. }
  909. - (PHLivePhotoRequestID)writeAfterCompletionRequestWithCompletion:(HXModelLivePhotoSuccessBlock _Nullable)completion{
  910. HXWeakSelf
  911. NSURL *imageURL = [NSURL fileURLWithPath:[[HXPhotoTools getLivePhotoImageURLFilePath:self.imageURL] stringByAppendingString:@".jpg"]];
  912. NSURL *videoURL = [NSURL fileURLWithPath:[[HXPhotoTools getLivePhotoVideoURLFilePath:self.videoURL] stringByAppendingString:@".mov"]];
  913. return [PHLivePhoto requestLivePhotoWithResourceFileURLs:[NSArray arrayWithObjects:videoURL, imageURL, nil] placeholderImage:self.thumbPhoto targetSize:CGSizeZero contentMode:PHImageContentModeAspectFill resultHandler:^(PHLivePhoto * _Nullable livePhoto, NSDictionary * _Nonnull info) {
  914. // BOOL downloadFinined = (![[info objectForKey:PHLivePhotoInfoCancelledKey] boolValue] && ![info objectForKey:PHLivePhotoInfoErrorKey]);
  915. BOOL isDegraded = [[info objectForKey:PHLivePhotoInfoIsDegradedKey] boolValue];
  916. if (!isDegraded) {
  917. if (completion) {
  918. completion(livePhoto, weakSelf, info);
  919. }
  920. }
  921. }];
  922. }
  923. - (PHImageRequestID)requestImageDataWithLoadOriginalImage:(BOOL)originalImage
  924. startRequestICloud:(HXModelStartRequestICloud)startRequestICloud
  925. progressHandler:(HXModelProgressHandler)progressHandler
  926. success:(HXModelImageDataSuccessBlock)success
  927. failed:(HXModelFailedBlock)failed {
  928. if (self.photoEdit && !originalImage) {
  929. if (success) success(self.photoEdit.editPreviewData, self.photoEdit.editPreviewImage.imageOrientation, self, nil);
  930. return 0;
  931. }
  932. HXWeakSelf
  933. if (self.type == HXPhotoModelMediaTypeCameraPhoto && self.networkPhotoUrl) {
  934. #if HasSDWebImage
  935. [[SDWebImageManager sharedManager] loadImageWithURL:self.networkPhotoUrl options:0 progress:nil completed:^(UIImage * _Nullable image, NSData * _Nullable data, NSError * _Nullable error, SDImageCacheType cacheType, BOOL finished, NSURL * _Nullable imageURL) {
  936. if (data) {
  937. dispatch_async(dispatch_get_main_queue(), ^{
  938. if (success) {
  939. success(data, 0, weakSelf, nil);
  940. }
  941. });
  942. }else {
  943. dispatch_async(dispatch_get_main_queue(), ^{
  944. if (failed) {
  945. failed(nil, weakSelf);
  946. }
  947. });
  948. }
  949. }];
  950. return 0;
  951. #elif HasYYKitOrWebImage
  952. [[YYWebImageManager sharedManager] requestImageWithURL:self.networkPhotoUrl options:0 progress:nil transform:nil completion:^(UIImage * _Nullable image, NSURL * _Nonnull url, YYWebImageFromType from, YYWebImageStage stage, NSError * _Nullable error) {
  953. if (image) {
  954. if (success) {
  955. NSData *imageData;
  956. if (UIImagePNGRepresentation(image)) {
  957. //返回为png图像。
  958. imageData = UIImagePNGRepresentation(image);
  959. }else {
  960. //返回为JPEG图像。
  961. imageData = UIImageJPEGRepresentation(image, 1.0);
  962. }
  963. dispatch_async(dispatch_get_main_queue(), ^{
  964. success(imageData, 0, weakSelf, nil);
  965. });
  966. }
  967. }else {
  968. dispatch_async(dispatch_get_main_queue(), ^{
  969. if (failed) {
  970. failed(nil, weakSelf);
  971. }
  972. });
  973. }
  974. }];
  975. return 0;
  976. #endif
  977. }
  978. PHImageRequestOptionsVersion version = 0;
  979. if (self.type == HXPhotoModelMediaTypePhotoGif) {
  980. version = PHImageRequestOptionsVersionOriginal;
  981. }
  982. self.iCloudDownloading = YES;
  983. PHImageRequestID requestID = [HXAssetManager requestImageDataForAsset:self.asset version:version resizeMode:PHImageRequestOptionsResizeModeFast networkAccessAllowed:NO progressHandler:nil completion:^(NSData * _Nonnull imageData, UIImageOrientation orientation, NSDictionary<NSString *,id> * _Nonnull info) {
  984. __strong typeof(self) strongSelf = self;
  985. [strongSelf requestDataWithResult:imageData info:info size:CGSizeZero resultClass:[NSData class] orientation:orientation audioMix:nil startRequestICloud:startRequestICloud progressHandler:progressHandler success:^(id result, NSDictionary *info, UIImageOrientation orientation, AVAudioMix *audioMix) {
  986. if (success) {
  987. success(result, orientation, strongSelf, info);
  988. }
  989. } failed:failed];
  990. }];
  991. self.iCloudRequestID = requestID;
  992. return requestID;
  993. }
  994. - (PHImageRequestID)requestImageDataStartRequestICloud:(HXModelStartRequestICloud)startRequestICloud
  995. progressHandler:(HXModelProgressHandler)progressHandler
  996. success:(HXModelImageDataSuccessBlock)success
  997. failed:(HXModelFailedBlock)failed {
  998. return [self requestImageDataWithLoadOriginalImage:NO startRequestICloud:startRequestICloud progressHandler:progressHandler success:success failed:failed];
  999. }
  1000. - (PHImageRequestID)requestAVAssetStartRequestICloud:(HXModelStartRequestICloud)startRequestICloud
  1001. progressHandler:(HXModelProgressHandler)progressHandler
  1002. success:(HXModelAVAssetSuccessBlock)success
  1003. failed:(HXModelFailedBlock)failed {
  1004. if (self.type == HXPhotoModelMediaTypeCameraVideo) {
  1005. if (success) {
  1006. AVAsset *asset = [AVAsset assetWithURL:self.videoURL];
  1007. success(asset, nil, self, nil);
  1008. }
  1009. return 0;
  1010. }
  1011. PHImageRequestID requestId = 0;
  1012. self.iCloudDownloading = YES;
  1013. requestId = [HXAssetManager requestAVAssetForAsset:self.asset networkAccessAllowed:YES progressHandler:^(double progress, NSError * _Nullable error, BOOL * _Nonnull stop, NSDictionary * _Nullable info) {
  1014. __strong typeof(self) strongSelf = self;
  1015. dispatch_async(dispatch_get_main_queue(), ^{
  1016. strongSelf.iCloudProgress = progress;
  1017. if (progressHandler) {
  1018. progressHandler(progress, strongSelf);
  1019. }
  1020. });
  1021. } completion:^(AVAsset * _Nonnull asset, AVAudioMix * _Nonnull audioMix, NSDictionary * _Nonnull info) {
  1022. __strong typeof(self) strongSelf = self;
  1023. [strongSelf requestDataWithResult:asset info:info size:CGSizeZero resultClass:[AVAsset class] orientation:0 audioMix:audioMix startRequestICloud:startRequestICloud progressHandler:progressHandler success:^(id result, NSDictionary *info, UIImageOrientation orientation, AVAudioMix *audioMix) {
  1024. if (success) {
  1025. success(result, audioMix, strongSelf, info);
  1026. }
  1027. } failed:failed];
  1028. }];
  1029. if (startRequestICloud) {
  1030. startRequestICloud(requestId, self);
  1031. }
  1032. self.iCloudRequestID = requestId;
  1033. return requestId;
  1034. }
  1035. - (PHImageRequestID)requestAVAssetExportSessionStartRequestICloud:(HXModelStartRequestICloud)startRequestICloud
  1036. progressHandler:(HXModelProgressHandler)progressHandler
  1037. success:(HXModelAVExportSessionSuccessBlock)success
  1038. failed:(HXModelFailedBlock)failed {
  1039. if (self.type == HXPhotoModelMediaTypeCameraVideo) {
  1040. AVAssetExportSession *export = [AVAssetExportSession exportSessionWithAsset:[AVAsset assetWithURL:self.videoURL] presetName:AVAssetExportPresetHighestQuality];
  1041. if (success) {
  1042. success(export, self, nil);
  1043. }
  1044. return 0;
  1045. }
  1046. PHImageRequestID requestId = 0;
  1047. self.iCloudDownloading = YES;
  1048. requestId = [HXAssetManager requestExportSessionForAsset:self.asset exportPreset:AVAssetExportPresetHighestQuality networkAccessAllowed:YES progressHandler:^(double progress, NSError * _Nullable error, BOOL * _Nonnull stop, NSDictionary * _Nullable info) {
  1049. __strong typeof(self) strongSelf = self;
  1050. dispatch_async(dispatch_get_main_queue(), ^{
  1051. strongSelf.iCloudProgress = progress;
  1052. if (progressHandler) {
  1053. progressHandler(progress, strongSelf);
  1054. }
  1055. });
  1056. } completion:^(AVAssetExportSession * _Nullable exportSession, NSDictionary * _Nullable info) {
  1057. __strong typeof(self) strongSelf = self;
  1058. [strongSelf requestDataWithResult:exportSession info:info size:CGSizeZero resultClass:[AVAssetExportSession class] orientation:0 audioMix:nil startRequestICloud:startRequestICloud progressHandler:progressHandler success:^(id result, NSDictionary *info, UIImageOrientation orientation, AVAudioMix *audioMix) {
  1059. if (success) {
  1060. success(result, strongSelf, info);
  1061. }
  1062. } failed:failed];
  1063. }];
  1064. if (startRequestICloud) {
  1065. startRequestICloud(requestId, self);
  1066. }
  1067. return requestId;
  1068. }
  1069. - (PHImageRequestID)requestAVPlayerItemStartRequestICloud:(HXModelStartRequestICloud)startRequestICloud
  1070. progressHandler:(HXModelProgressHandler)progressHandler
  1071. success:(HXModelAVPlayerItemSuccessBlock)success
  1072. failed:(HXModelFailedBlock)failed {
  1073. if (self.type == HXPhotoModelMediaTypeCameraVideo) {
  1074. AVPlayerItem *playerItem = [AVPlayerItem playerItemWithURL:self.videoURL];
  1075. if (success) {
  1076. success(playerItem, self, nil);
  1077. }
  1078. return 0;
  1079. }
  1080. PHImageRequestID requestId = 0;
  1081. self.iCloudDownloading = YES;
  1082. requestId = [HXAssetManager requestPlayerItemForAsset:self.asset networkAccessAllowed:YES progressHandler:^(double progress, NSError * _Nullable error, BOOL * _Nonnull stop, NSDictionary * _Nullable info) {
  1083. __strong typeof(self) strongSelf = self;
  1084. dispatch_async(dispatch_get_main_queue(), ^{
  1085. strongSelf.iCloudProgress = progress;
  1086. if (progressHandler) {
  1087. progressHandler(progress, strongSelf);
  1088. }
  1089. });
  1090. } completion:^(AVPlayerItem * _Nullable playerItem, NSDictionary * _Nullable info) {
  1091. __strong typeof(self) strongSelf = self;
  1092. [strongSelf requestDataWithResult:playerItem info:info size:CGSizeZero resultClass:[AVPlayerItem class] orientation:0 audioMix:nil startRequestICloud:startRequestICloud progressHandler:progressHandler success:^(id result, NSDictionary *info, UIImageOrientation orientation, AVAudioMix *audioMix) {
  1093. if (success) {
  1094. success(result, strongSelf, info);
  1095. }
  1096. } failed:failed];
  1097. }];
  1098. if (startRequestICloud) {
  1099. startRequestICloud(requestId, self);
  1100. }
  1101. return requestId;
  1102. }
  1103. - (void)requestDataWithResult:(id)results
  1104. info:(NSDictionary *)info
  1105. size:(CGSize)size
  1106. resultClass:(Class)resultClass
  1107. orientation:(UIImageOrientation)orientation
  1108. audioMix:(AVAudioMix *)audioMix
  1109. startRequestICloud:(HXModelStartRequestICloud)startRequestICloud
  1110. progressHandler:(HXModelProgressHandler)progressHandler
  1111. success:(void (^)(id result, NSDictionary *info, UIImageOrientation orientation, AVAudioMix *audioMix))success
  1112. failed:(HXModelFailedBlock)failed {
  1113. BOOL downloadFinined = [HXAssetManager downloadFininedForInfo:info];
  1114. if (downloadFinined && results) {
  1115. self.iCloudDownloading = NO;
  1116. if (success) {
  1117. success(results, info, orientation, audioMix);
  1118. }
  1119. return;
  1120. }else {
  1121. if ([HXAssetManager isInCloudForInfo:info]) {
  1122. PHImageRequestID iCloudRequestId = 0;
  1123. PHAssetImageProgressHandler imageProgressHanlder = ^(double progress, NSError * _Nullable error, BOOL * _Nonnull stop, NSDictionary * _Nullable info) {
  1124. __strong typeof(self) strongSelf = self;
  1125. dispatch_async(dispatch_get_main_queue(), ^{
  1126. strongSelf.iCloudProgress = progress;
  1127. if (progressHandler) {
  1128. progressHandler(progress, strongSelf);
  1129. }
  1130. });
  1131. };
  1132. if ([resultClass isEqual:[UIImage class]]) {
  1133. iCloudRequestId = [HXAssetManager requestPreviewImageForAsset:self.asset targetSize:size networkAccessAllowed:YES progressHandler:imageProgressHanlder completion:^(UIImage * _Nonnull result, NSDictionary<NSString *,id> * _Nonnull info) {
  1134. __strong typeof(self) strongSelf = self;
  1135. BOOL downloadFinined = [HXAssetManager downloadFininedForInfo:info];
  1136. if (downloadFinined && result) {
  1137. strongSelf.iCloudDownloading = NO;
  1138. if (success) {
  1139. success(result, info, 0, nil);
  1140. }
  1141. }else {
  1142. if (![[info objectForKey:PHImageCancelledKey] boolValue]) {
  1143. strongSelf.iCloudDownloading = NO;
  1144. }
  1145. if (failed) {
  1146. failed(info, strongSelf);
  1147. }
  1148. }
  1149. }];
  1150. }else if ([resultClass isEqual:[PHLivePhoto class]]) {
  1151. iCloudRequestId = [HXAssetManager requestPreviewLivePhotoForAsset:self.asset targetSize:size networkAccessAllowed:YES progressHandler:imageProgressHanlder completion:^(PHLivePhoto * _Nonnull livePhoto, NSDictionary<NSString *,id> * _Nonnull info) {
  1152. __strong typeof(self) strongSelf = self;
  1153. BOOL downloadFinined = [HXAssetManager downloadFininedForInfo:info];
  1154. if (downloadFinined && livePhoto) {
  1155. strongSelf.iCloudDownloading = NO;
  1156. if (success) {
  1157. success(livePhoto, info, 0, nil);
  1158. }
  1159. }else {
  1160. if (![[info objectForKey:PHImageCancelledKey] boolValue]) {
  1161. strongSelf.iCloudDownloading = NO;
  1162. }
  1163. if (failed) {
  1164. failed(info, strongSelf);
  1165. }
  1166. }
  1167. }];
  1168. }else if ([resultClass isEqual:[NSData class]]) {
  1169. PHImageRequestOptionsVersion version = 0;
  1170. if (self.type == HXPhotoModelMediaTypePhotoGif) {
  1171. version = PHImageRequestOptionsVersionOriginal;
  1172. }
  1173. iCloudRequestId = [HXAssetManager requestImageDataForAsset:self.asset version:version resizeMode:PHImageRequestOptionsResizeModeFast networkAccessAllowed:YES progressHandler:imageProgressHanlder completion:^(NSData * _Nonnull imageData, UIImageOrientation orientation, NSDictionary<NSString *,id> * _Nonnull info) {
  1174. __strong typeof(self) strongSelf = self;
  1175. BOOL downloadFinined = [HXAssetManager downloadFininedForInfo:info];
  1176. if (downloadFinined && imageData) {
  1177. strongSelf.iCloudDownloading = NO;
  1178. if (success) {
  1179. success(imageData, info, orientation, nil);
  1180. }
  1181. }else {
  1182. if (![[info objectForKey:PHImageCancelledKey] boolValue]) {
  1183. strongSelf.iCloudDownloading = NO;
  1184. }
  1185. if (failed) {
  1186. failed(info, strongSelf);
  1187. }
  1188. }
  1189. }];
  1190. }else if ([resultClass isEqual:[AVAsset class]]) {
  1191. iCloudRequestId = [HXAssetManager requestAVAssetForAsset:self.asset networkAccessAllowed:YES progressHandler:^(double progress, NSError * _Nullable error, BOOL * _Nonnull stop, NSDictionary * _Nullable info) {
  1192. __strong typeof(self) strongSelf = self;
  1193. dispatch_async(dispatch_get_main_queue(), ^{
  1194. strongSelf.iCloudProgress = progress;
  1195. if (progressHandler) {
  1196. progressHandler(progress, strongSelf);
  1197. }
  1198. });
  1199. } completion:^(AVAsset * _Nonnull asset, AVAudioMix * _Nonnull audioMix, NSDictionary * _Nonnull info) {
  1200. __strong typeof(self) strongSelf = self;
  1201. BOOL downloadFinined = [HXAssetManager downloadFininedForInfo:info];
  1202. if (downloadFinined && asset) {
  1203. strongSelf.iCloudDownloading = NO;
  1204. if (success) {
  1205. success(asset, info, 0, audioMix);
  1206. }
  1207. }else {
  1208. if (![[info objectForKey:PHImageCancelledKey] boolValue]) {
  1209. strongSelf.iCloudDownloading = NO;
  1210. }
  1211. if (failed) {
  1212. failed(info, strongSelf);
  1213. }
  1214. }
  1215. }];
  1216. }else if ([resultClass isEqual:[AVAssetExportSession class]]) {
  1217. iCloudRequestId = [HXAssetManager requestExportSessionForAsset:self.asset exportPreset:AVAssetExportPresetHighestQuality networkAccessAllowed:YES progressHandler:^(double progress, NSError * _Nullable error, BOOL * _Nonnull stop, NSDictionary * _Nullable info) {
  1218. __strong typeof(self) strongSelf = self;
  1219. dispatch_async(dispatch_get_main_queue(), ^{
  1220. strongSelf.iCloudProgress = progress;
  1221. if (progressHandler) {
  1222. progressHandler(progress, strongSelf);
  1223. }
  1224. });
  1225. } completion:^(AVAssetExportSession * _Nullable exportSession, NSDictionary * _Nullable info) {
  1226. __strong typeof(self) strongSelf = self;
  1227. BOOL downloadFinined = [HXAssetManager downloadFininedForInfo:info];
  1228. if (downloadFinined && exportSession) {
  1229. strongSelf.iCloudDownloading = NO;
  1230. if (success) {
  1231. success(exportSession, info, 0, nil);
  1232. }
  1233. }else {
  1234. if (![[info objectForKey:PHImageCancelledKey] boolValue]) {
  1235. strongSelf.iCloudDownloading = NO;
  1236. }
  1237. if (failed) {
  1238. failed(info, strongSelf);
  1239. }
  1240. }
  1241. }];
  1242. }else if ([resultClass isEqual:[AVPlayerItem class]]) {
  1243. iCloudRequestId = [HXAssetManager requestPlayerItemForAsset:self.asset networkAccessAllowed:YES progressHandler:^(double progress, NSError * _Nullable error, BOOL * _Nonnull stop, NSDictionary * _Nullable info) {
  1244. __strong typeof(self) strongSelf = self;
  1245. dispatch_async(dispatch_get_main_queue(), ^{
  1246. strongSelf.iCloudProgress = progress;
  1247. if (progressHandler) {
  1248. progressHandler(progress, strongSelf);
  1249. }
  1250. });
  1251. } completion:^(AVPlayerItem * _Nullable playerItem, NSDictionary * _Nullable info) {
  1252. __strong typeof(self) strongSelf = self;
  1253. BOOL downloadFinined = [HXAssetManager downloadFininedForInfo:info];
  1254. if (downloadFinined && playerItem) {
  1255. strongSelf.iCloudDownloading = NO;
  1256. if (success) {
  1257. success(playerItem, info, 0, nil);
  1258. }
  1259. }else {
  1260. if (![[info objectForKey:PHImageCancelledKey] boolValue]) {
  1261. strongSelf.iCloudDownloading = NO;
  1262. }
  1263. if (failed) {
  1264. failed(info, strongSelf);
  1265. }
  1266. }
  1267. }];
  1268. }else if ([resultClass isEqual:[PHContentEditingInput class]]) {
  1269. }
  1270. self.iCloudRequestID = iCloudRequestId;
  1271. if (startRequestICloud) {
  1272. startRequestICloud(iCloudRequestId, self);
  1273. }
  1274. return;
  1275. }
  1276. }
  1277. if (![[info objectForKey:PHImageCancelledKey] boolValue]) {
  1278. self.iCloudDownloading = NO;
  1279. }
  1280. if (failed) {
  1281. failed(info, self);
  1282. }
  1283. }
  1284. - (void)exportVideoWithPresetName:(NSString *)presetName
  1285. startRequestICloud:(HXModelStartRequestICloud)startRequestICloud
  1286. iCloudProgressHandler:(HXModelProgressHandler)iCloudProgressHandler
  1287. exportProgressHandler:(HXModelExportVideoProgressHandler)exportProgressHandler
  1288. success:(HXModelExportVideoSuccessBlock)success
  1289. failed:(HXModelFailedBlock)failed {
  1290. if (self.type == HXPhotoModelMediaTypeCameraVideo) {
  1291. if (success) {
  1292. success(self.videoURL, self);
  1293. }
  1294. return;
  1295. }
  1296. if (!presetName) {
  1297. presetName = AVAssetExportPresetMediumQuality;
  1298. }
  1299. // PHVideoRequestOptionsDeliveryMode mode = [presetName isEqualToString:AVAssetExportPresetHighestQuality] ? PHVideoRequestOptionsDeliveryModeHighQualityFormat : PHVideoRequestOptionsDeliveryModeFastFormat;
  1300. [self requestAVAssetStartRequestICloud:startRequestICloud progressHandler:iCloudProgressHandler success:^(AVAsset * _Nullable avAsset, AVAudioMix * _Nullable audioMix, HXPhotoModel * _Nullable model, NSDictionary * _Nullable info) {
  1301. NSArray *presets = [AVAssetExportSession exportPresetsCompatibleWithAsset:avAsset];
  1302. if ([presets containsObject:presetName]) {
  1303. AVAssetExportSession *session = [[AVAssetExportSession alloc] initWithAsset:avAsset presetName:presetName];
  1304. NSString *fileName = [[NSString hx_fileName] stringByAppendingString:@".mp4"];
  1305. NSString *fullPathToFile = [NSTemporaryDirectory() stringByAppendingPathComponent:fileName];
  1306. NSURL *videoURL = [NSURL fileURLWithPath:fullPathToFile];
  1307. session.outputURL = videoURL;
  1308. session.shouldOptimizeForNetworkUse = YES;
  1309. NSArray *supportedTypeArray = session.supportedFileTypes;
  1310. if ([supportedTypeArray containsObject:AVFileTypeMPEG4]) {
  1311. session.outputFileType = AVFileTypeMPEG4;
  1312. } else if (supportedTypeArray.count == 0) {
  1313. if (failed) {
  1314. failed(nil, model);
  1315. }
  1316. if (HXShowLog) NSSLog(@"不支持导入该类型视频");
  1317. return;
  1318. }else {
  1319. session.outputFileType = [supportedTypeArray objectAtIndex:0];
  1320. }
  1321. NSTimer *timer = [NSTimer hx_scheduledTimerWithTimeInterval:0.1f block:^{
  1322. if (exportProgressHandler) {
  1323. exportProgressHandler(session.progress, self);
  1324. }
  1325. } repeats:YES];
  1326. [session exportAsynchronouslyWithCompletionHandler:^{
  1327. dispatch_async(dispatch_get_main_queue(), ^{
  1328. if ([session status] == AVAssetExportSessionStatusCompleted) {
  1329. [timer invalidate];
  1330. self.videoURL = videoURL;
  1331. if (success) {
  1332. success(videoURL, self);
  1333. }
  1334. }else if ([session status] == AVAssetExportSessionStatusFailed){
  1335. [timer invalidate];
  1336. [self getVideoURLWithSuccess:^(NSURL * _Nullable URL, HXPhotoModelMediaSubType mediaType, BOOL isNetwork, HXPhotoModel * _Nullable model) {
  1337. self.videoURL = URL;
  1338. if (success) {
  1339. success(URL, self);
  1340. }
  1341. if (HXShowLog) NSSLog(@"视频导出完成");
  1342. } failed:^(NSDictionary * _Nullable info, HXPhotoModel * _Nullable model) {
  1343. if (failed) {
  1344. failed(nil, self);
  1345. }
  1346. if (HXShowLog) NSSLog(@"视频导出失败");
  1347. }];
  1348. }else if ([session status] == AVAssetExportSessionStatusCancelled) {
  1349. if (HXShowLog) NSSLog(@"视频导出被取消");
  1350. [timer invalidate];
  1351. if (failed) {
  1352. failed(nil, self);
  1353. }
  1354. }
  1355. });
  1356. }];
  1357. }else {
  1358. if (failed) {
  1359. failed(nil, self);
  1360. }
  1361. if (HXShowLog) NSSLog(@"该设备不支持:%@",presetName);
  1362. }
  1363. } failed:failed];
  1364. }
  1365. - (PHContentEditingInputRequestID)requestImageURLStartRequestICloud:(void (^)(PHContentEditingInputRequestID iCloudRequestId, HXPhotoModel *model))startRequestICloud
  1366. progressHandler:(HXModelProgressHandler)progressHandler
  1367. success:(HXModelImageURLSuccessBlock)success
  1368. failed:(HXModelFailedBlock)failed {
  1369. if (self.photoEdit) {
  1370. // HXWeakSelf
  1371. [self getCameraImageURLWithSuccess:^(NSURL * _Nullable imageURL, HXPhotoModel * _Nullable model, NSDictionary * _Nullable info) {
  1372. if (success) {
  1373. success(imageURL, model, nil);
  1374. }
  1375. } failed:^(NSDictionary * _Nullable info, HXPhotoModel * _Nullable model) {
  1376. if (failed) {
  1377. failed(info, model);
  1378. }
  1379. }];
  1380. return 0;
  1381. }
  1382. if (self.type == HXPhotoModelMediaTypeCameraPhoto) {
  1383. if (self.imageURL) {
  1384. if (success) {
  1385. success(self.imageURL, self, nil);
  1386. }
  1387. }else {
  1388. if (failed) {
  1389. failed(nil, self);
  1390. }
  1391. }
  1392. // if (self.networkPhotoUrl) {
  1393. // if (success) {
  1394. // success(self.networkPhotoUrl, self, nil);
  1395. // }
  1396. // }else {
  1397. // //
  1398. //
  1399. // }
  1400. return 0;
  1401. }
  1402. PHContentEditingInputRequestOptions *options = [[PHContentEditingInputRequestOptions alloc] init];
  1403. options.networkAccessAllowed = NO;
  1404. HXWeakSelf
  1405. return [self.asset requestContentEditingInputWithOptions:options completionHandler:^(PHContentEditingInput * _Nullable contentEditingInput, NSDictionary * _Nonnull info) {
  1406. BOOL downloadFinined = (![[info objectForKey:PHContentEditingInputCancelledKey] boolValue] && ![info objectForKey:PHContentEditingInputErrorKey]);
  1407. if (downloadFinined && contentEditingInput.fullSizeImageURL) {
  1408. NSURL *imageURL;
  1409. if ([[contentEditingInput.fullSizeImageURL pathExtension] isEqualToString:@"GIF"] && weakSelf.type != HXPhotoModelMediaTypePhotoGif) {
  1410. // 虽然是gif图片,但是没有开启显示gif 所以这里处理一下
  1411. NSData *imageData = UIImageJPEGRepresentation(contentEditingInput.displaySizeImage, 1);
  1412. NSString *fileName = [[NSString hx_fileName] stringByAppendingString:@".jpg"];
  1413. NSString *fullPathToFile = [NSTemporaryDirectory() stringByAppendingPathComponent:fileName];
  1414. imageURL = [NSURL fileURLWithPath:fullPathToFile];
  1415. if (![imageData writeToURL:imageURL atomically:YES]) {
  1416. dispatch_async(dispatch_get_main_queue(), ^{
  1417. if (failed) {
  1418. failed(info, weakSelf);
  1419. }
  1420. });
  1421. return;
  1422. }
  1423. }else {
  1424. imageURL = contentEditingInput.fullSizeImageURL;
  1425. }
  1426. weakSelf.imageURL = imageURL;
  1427. dispatch_async(dispatch_get_main_queue(), ^{
  1428. if (success) {
  1429. success(imageURL, weakSelf, info);
  1430. }
  1431. });
  1432. }else {
  1433. if ([[info objectForKey:PHContentEditingInputResultIsInCloudKey] boolValue] &&
  1434. ![[info objectForKey:PHContentEditingInputCancelledKey] boolValue]) {
  1435. PHContentEditingInputRequestOptions *iCloudOptions = [[PHContentEditingInputRequestOptions alloc] init];
  1436. iCloudOptions.networkAccessAllowed = YES;
  1437. iCloudOptions.progressHandler = ^(double progress, BOOL * _Nonnull stop) {
  1438. dispatch_async(dispatch_get_main_queue(), ^{
  1439. if (progressHandler) {
  1440. progressHandler(progress, weakSelf);
  1441. }
  1442. });
  1443. };
  1444. PHContentEditingInputRequestID iCloudRequestID = [weakSelf.asset requestContentEditingInputWithOptions:iCloudOptions completionHandler:^(PHContentEditingInput * _Nullable contentEditingInput, NSDictionary * _Nonnull info) {
  1445. BOOL downloadFinined = (![[info objectForKey:PHContentEditingInputCancelledKey] boolValue] && ![info objectForKey:PHContentEditingInputErrorKey]);
  1446. if (downloadFinined && contentEditingInput.fullSizeImageURL) {
  1447. NSURL *imageURL;
  1448. if ([[contentEditingInput.fullSizeImageURL pathExtension] isEqualToString:@"GIF"] && weakSelf.type != HXPhotoModelMediaTypePhotoGif) {
  1449. // 虽然是gif图片,但是没有开启显示gif 所以这里处理一下
  1450. NSData *imageData = UIImageJPEGRepresentation(contentEditingInput.displaySizeImage, 1);
  1451. NSString *fileName = [[NSString hx_fileName] stringByAppendingString:@".jpg"];
  1452. NSString *fullPathToFile = [NSTemporaryDirectory() stringByAppendingPathComponent:fileName];
  1453. imageURL = [NSURL fileURLWithPath:fullPathToFile];
  1454. if (![imageData writeToURL:imageURL atomically:YES]) {
  1455. dispatch_async(dispatch_get_main_queue(), ^{
  1456. if (failed) {
  1457. failed(info, weakSelf);
  1458. }
  1459. });
  1460. return;
  1461. }
  1462. }else {
  1463. imageURL = contentEditingInput.fullSizeImageURL;
  1464. }
  1465. weakSelf.imageURL = imageURL;
  1466. dispatch_async(dispatch_get_main_queue(), ^{
  1467. if (success) {
  1468. success(imageURL, weakSelf, nil);
  1469. }
  1470. });
  1471. }else {
  1472. dispatch_async(dispatch_get_main_queue(), ^{
  1473. if (failed) {
  1474. failed(info, weakSelf);
  1475. }
  1476. });
  1477. }
  1478. }];
  1479. dispatch_async(dispatch_get_main_queue(), ^{
  1480. if (startRequestICloud) {
  1481. startRequestICloud(iCloudRequestID, weakSelf);
  1482. }
  1483. });
  1484. }else {
  1485. dispatch_async(dispatch_get_main_queue(), ^{
  1486. if (failed) {
  1487. failed(info, weakSelf);
  1488. }
  1489. });
  1490. }
  1491. }
  1492. }];
  1493. }
  1494. - (void)requestLivePhotoAssetsWithSuccess:(HXModelLivePhotoAssetsSuccessBlock _Nullable)success
  1495. failed:(HXModelFailedBlock _Nullable)failed {
  1496. if (self.photoEdit) {
  1497. [self getCameraImageURLWithSuccess:^(NSURL * _Nullable imageURL, HXPhotoModel * _Nullable model, NSDictionary * _Nullable info) {
  1498. if (success) {
  1499. success(imageURL, nil, NO, model);
  1500. }
  1501. } failed:^(NSDictionary * _Nullable info, HXPhotoModel * _Nullable model) {
  1502. if (failed) {
  1503. failed(info, model);
  1504. }
  1505. }];
  1506. return;
  1507. }
  1508. if (self.cameraPhotoType == HXPhotoModelMediaTypeCameraPhotoTypeLocalLivePhoto) {
  1509. if (success) {
  1510. success(self.imageURL, self.videoURL, NO, self);
  1511. }
  1512. return;
  1513. }else if (self.cameraPhotoType == HXPhotoModelMediaTypeCameraPhotoTypeNetWorkLivePhoto) {
  1514. if (success) {
  1515. success(self.networkPhotoUrl, self.livePhotoVideoURL, YES, self);
  1516. }
  1517. return;
  1518. // if (self.imageURL && self.videoURL) {
  1519. // if (success) {
  1520. // success(self.imageURL, self.videoURL, self);
  1521. // }
  1522. // return;
  1523. // }
  1524. }
  1525. HXWeakSelf
  1526. [self requestLivePhotoWithSize:PHImageManagerMaximumSize startRequestICloud:nil progressHandler:nil success:^(PHLivePhoto * _Nullable livePhoto, HXPhotoModel * _Nullable model, NSDictionary * _Nullable info) {
  1527. dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
  1528. [weakSelf requestLivePhotoAssetResourcesWithLivePhoto:livePhoto success:^(NSURL * _Nullable imageURL, NSURL * _Nullable videoURL) {
  1529. dispatch_async(dispatch_get_main_queue(), ^{
  1530. weakSelf.imageURL = imageURL;
  1531. weakSelf.videoURL = videoURL;
  1532. if (success) {
  1533. success(imageURL, videoURL, NO, weakSelf);
  1534. }
  1535. });
  1536. } failed:^{
  1537. dispatch_async(dispatch_get_main_queue(), ^{
  1538. if (failed) {
  1539. failed(info, model);
  1540. }
  1541. });
  1542. }];
  1543. });
  1544. } failed:^(NSDictionary * _Nullable info, HXPhotoModel * _Nullable model) {
  1545. if (failed) {
  1546. failed(info, model);
  1547. }
  1548. }];
  1549. }
  1550. - (void)requestLivePhotoAssetResourcesWithLivePhoto:(PHLivePhoto *)livePhoto success:(void (^ _Nullable)(NSURL * _Nullable imageURL, NSURL * _Nullable videoURL))success failed:(void (^ _Nullable)(void))failed {
  1551. NSArray *resoures = [PHAssetResource assetResourcesForLivePhoto:livePhoto];
  1552. // resoures 里面有两个 PHAssetResource 一个图片,一个视频
  1553. PHAssetResourceRequestOptions *options = [[PHAssetResourceRequestOptions alloc] init];
  1554. options.networkAccessAllowed = YES;
  1555. NSString *fileName = [[NSString hx_fileName] stringByAppendingString:@".mp4"];
  1556. NSString *fullPathToFile = [NSTemporaryDirectory() stringByAppendingPathComponent:fileName];
  1557. // 导出livePhoto视频的本地地址
  1558. NSURL *videoURL = [NSURL fileURLWithPath:fullPathToFile];
  1559. NSString *videoFullPathToFile = [NSTemporaryDirectory() stringByAppendingPathComponent:[[NSString hx_fileName] stringByAppendingString:@".jpg"]];
  1560. NSURL *imageURL = [NSURL fileURLWithPath:videoFullPathToFile];
  1561. __block BOOL requestImageURLCompletion = NO;
  1562. __block BOOL requestVideoURLCompletion = NO;
  1563. for (PHAssetResource *assetResource in resoures) {
  1564. if (assetResource.type == PHAssetResourceTypePhoto) {
  1565. // LivePhoto的封面
  1566. [[PHAssetResourceManager defaultManager] requestDataForAssetResource:assetResource options:options dataReceivedHandler:^(NSData * _Nonnull data) {
  1567. BOOL writeSuccesss = [data writeToURL:imageURL atomically:YES];
  1568. if (writeSuccesss) {
  1569. if (success && requestVideoURLCompletion) {
  1570. success(imageURL, videoURL);
  1571. }
  1572. }else {
  1573. if (failed) {
  1574. failed();
  1575. }
  1576. }
  1577. } completionHandler:^(NSError * _Nullable error) {
  1578. if (!error) {
  1579. requestImageURLCompletion = YES;
  1580. }else {
  1581. if (failed) {
  1582. failed();
  1583. }
  1584. }
  1585. }];
  1586. }else if (assetResource.type == PHAssetResourceTypePairedVideo) {
  1587. // LivePhoto的视频内容
  1588. [[PHAssetResourceManager defaultManager] writeDataForAssetResource:assetResource toFile:videoURL options:options completionHandler:^(NSError * _Nullable error) {
  1589. if (!error) {
  1590. requestVideoURLCompletion = YES;
  1591. if (success && requestImageURLCompletion) {
  1592. success(imageURL, videoURL);
  1593. }
  1594. }else {
  1595. if (failed) {
  1596. failed();
  1597. }
  1598. }
  1599. }];
  1600. }
  1601. }
  1602. }
  1603. - (void)getCameraImageURLWithSuccess:(HXModelImageURLSuccessBlock _Nullable)success
  1604. failed:(HXModelFailedBlock _Nullable)failed {
  1605. HXWeakSelf
  1606. if (self.photoEdit) {
  1607. [self getImageURLWithImage:self.photoEdit.editPreviewImage success:^(NSURL * _Nullable imageURL, HXPhotoModel * _Nullable model, NSDictionary * _Nullable info) {
  1608. weakSelf.imageURL = imageURL;
  1609. if (success) {
  1610. success(imageURL, weakSelf, nil);
  1611. }
  1612. } failed:^(NSDictionary * _Nullable info, HXPhotoModel * _Nullable model) {
  1613. if (failed) {
  1614. failed(nil, weakSelf);
  1615. }
  1616. }];
  1617. return;
  1618. }
  1619. if (self.type != HXPhotoModelMediaTypeCameraPhoto) {
  1620. if (failed) {
  1621. failed(nil, self);
  1622. }
  1623. return;
  1624. }
  1625. if (self.cameraPhotoType == HXPhotoModelMediaTypeCameraPhotoTypeLocalLivePhoto) {
  1626. if (success) {
  1627. success(self.imageURL, self, nil);
  1628. }
  1629. return;
  1630. }
  1631. [self getImageURLWithImage:self.thumbPhoto success:^(NSURL * _Nullable imageURL, HXPhotoModel * _Nullable model, NSDictionary * _Nullable info) {
  1632. weakSelf.imageURL = imageURL;
  1633. if (success) {
  1634. success(imageURL, weakSelf, nil);
  1635. }
  1636. } failed:^(NSDictionary * _Nullable info, HXPhotoModel * _Nullable model) {
  1637. if (failed) {
  1638. failed(nil, weakSelf);
  1639. }
  1640. }];
  1641. }
  1642. - (void)getImageWithSuccess:(HXModelImageSuccessBlock _Nullable)success
  1643. failed:(HXModelFailedBlock _Nullable)failed {
  1644. if (self.cameraPhotoType == HXPhotoModelMediaTypeCameraPhotoTypeLocalLivePhoto) {
  1645. if (self.thumbPhoto) {
  1646. if (success) {
  1647. success(self.thumbPhoto, self, nil);
  1648. }
  1649. return;
  1650. }else if (self.imageURL) {
  1651. UIImage *image = [UIImage imageWithContentsOfFile:self.imageURL.path];
  1652. if (image && success) {
  1653. self.thumbPhoto = image;
  1654. self.previewPhoto = image;
  1655. success(image, self, nil);
  1656. return;
  1657. }
  1658. }
  1659. }
  1660. [self requestPreviewImageWithSize:PHImageManagerMaximumSize startRequestICloud:nil progressHandler:nil success:success failed:failed];
  1661. }
  1662. - (void)getImageURLWithImage:(UIImage *)image
  1663. success:(HXModelImageURLSuccessBlock _Nullable)success
  1664. failed:(HXModelFailedBlock _Nullable)failed{
  1665. dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
  1666. NSData *imageData;
  1667. NSString *suffix;
  1668. if (self.photoEdit) {
  1669. imageData = self.photoEdit.editPreviewData;
  1670. suffix = @"jpeg";
  1671. }else {
  1672. if (UIImagePNGRepresentation(image)) {
  1673. //返回为png图像。
  1674. imageData = UIImagePNGRepresentation(image);
  1675. suffix = @"png";
  1676. }else {
  1677. //返回为JPEG图像。
  1678. imageData = UIImageJPEGRepresentation(image, 1);
  1679. suffix = @"jpeg";
  1680. }
  1681. }
  1682. NSString *fileName = [[NSString hx_fileName] stringByAppendingString:[NSString stringWithFormat:@".%@",suffix]];
  1683. NSString *fullPathToFile = [NSTemporaryDirectory() stringByAppendingPathComponent:fileName];
  1684. NSURL *imageURL = [self writeWithImageData:imageData toFile:fullPathToFile];
  1685. if (imageURL != nil) {
  1686. dispatch_async(dispatch_get_main_queue(), ^{
  1687. if (success) {
  1688. success(imageURL, self, nil);
  1689. }
  1690. });
  1691. }else {
  1692. dispatch_async(dispatch_get_main_queue(), ^{
  1693. if (failed) {
  1694. failed(nil, self);
  1695. }
  1696. });
  1697. }
  1698. });
  1699. }
  1700. - (void)getImageURLWithImageData:(NSData *)imageData
  1701. success:(HXModelImageURLSuccessBlock _Nullable)success
  1702. failed:(HXModelFailedBlock _Nullable)failed{
  1703. dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
  1704. NSString *suffix;
  1705. if (self.photoEdit) {
  1706. suffix = @"jpeg";
  1707. }else {
  1708. if (UIImagePNGRepresentation([UIImage imageWithData:imageData])) {
  1709. suffix = @"png";
  1710. }else {
  1711. suffix = @"jpeg";
  1712. }
  1713. }
  1714. NSString *fileName = [[NSString hx_fileName] stringByAppendingString:[NSString stringWithFormat:@".%@",suffix]];
  1715. NSString *fullPathToFile = [NSTemporaryDirectory() stringByAppendingPathComponent:fileName];
  1716. NSURL *imageURL = [self writeWithImageData:imageData toFile:fullPathToFile];
  1717. if (imageURL != nil) {
  1718. dispatch_async(dispatch_get_main_queue(), ^{
  1719. if (success) {
  1720. success(imageURL, self, nil);
  1721. }
  1722. });
  1723. }else {
  1724. dispatch_async(dispatch_get_main_queue(), ^{
  1725. if (failed) {
  1726. failed(nil, self);
  1727. }
  1728. });
  1729. }
  1730. });
  1731. }
  1732. - (NSURL *)writeWithImageData:(NSData *)imageData toFile:(NSString *)filePath {
  1733. if ([imageData writeToFile:filePath atomically:YES]) {
  1734. return [NSURL fileURLWithPath:filePath];
  1735. }else {
  1736. return nil;
  1737. }
  1738. }
  1739. - (void)getAssetURLWithSuccess:(HXModelURLHandler)success
  1740. failed:(HXModelFailedBlock)failed {
  1741. [self getAssetURLWithVideoPresetName:nil success:success failed:failed];
  1742. }
  1743. - (void)getAssetURLWithVideoPresetName:(NSString * _Nullable)presetName
  1744. success:(HXModelURLHandler _Nullable)success
  1745. failed:(HXModelFailedBlock _Nullable)failed {
  1746. HXWeakSelf
  1747. if (self.photoEdit) {
  1748. [self getCameraImageURLWithSuccess:^(NSURL * _Nullable imageURL, HXPhotoModel * _Nullable model, NSDictionary * _Nullable info) {
  1749. if (success) {
  1750. success(imageURL, HXPhotoModelMediaSubTypePhoto, NO, weakSelf);
  1751. }
  1752. } failed:^(NSDictionary * _Nullable info, HXPhotoModel * _Nullable model) {
  1753. if (failed) {
  1754. failed(nil, weakSelf);
  1755. }
  1756. }];
  1757. return;
  1758. }
  1759. if (self.subType == HXPhotoModelMediaSubTypePhoto) {
  1760. if (self.type == HXPhotoModelMediaTypeCameraPhoto) {
  1761. if (self.cameraPhotoType == HXPhotoModelMediaTypeCameraPhotoTypeNetWork ||
  1762. self.cameraPhotoType == HXPhotoModelMediaTypeCameraPhotoTypeNetWorkGif) {
  1763. if (success) {
  1764. success(self.networkPhotoUrl, HXPhotoModelMediaSubTypePhoto, YES, self);
  1765. }
  1766. }else {
  1767. [self getCameraImageURLWithSuccess:^(NSURL * _Nullable imageURL, HXPhotoModel * _Nullable model, NSDictionary * _Nullable info) {
  1768. if (success) {
  1769. success(imageURL, HXPhotoModelMediaSubTypePhoto, NO, weakSelf);
  1770. }
  1771. } failed:^(NSDictionary * _Nullable info, HXPhotoModel * _Nullable model) {
  1772. if (failed) {
  1773. failed(nil, weakSelf);
  1774. }
  1775. }];
  1776. }
  1777. }else {
  1778. [self requestImageDataStartRequestICloud:nil progressHandler:nil success:^(NSData * _Nullable imageData, UIImageOrientation orientation, HXPhotoModel * _Nullable model, NSDictionary * _Nullable info) {
  1779. if (model.type == HXPhotoModelMediaTypePhotoGif) {
  1780. dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
  1781. NSString *fileName = [[NSString hx_fileName] stringByAppendingString:@".gif"];
  1782. NSString *fullPathToFile = [NSTemporaryDirectory() stringByAppendingPathComponent:fileName];
  1783. NSURL *imageURL = [weakSelf writeWithImageData:imageData toFile:fullPathToFile];
  1784. dispatch_async(dispatch_get_main_queue(), ^{
  1785. if (imageURL != nil) {
  1786. weakSelf.imageURL = imageURL;
  1787. if (success) {
  1788. success(imageURL, HXPhotoModelMediaSubTypePhoto, NO, weakSelf);
  1789. }
  1790. }else {
  1791. if (failed) {
  1792. failed(nil, weakSelf);
  1793. }
  1794. }
  1795. });
  1796. });
  1797. return;
  1798. }
  1799. if (orientation != UIImageOrientationUp) {
  1800. UIImage *image = [[[UIImage alloc] initWithData:imageData] hx_normalizedImage];
  1801. [weakSelf getImageURLWithImage:image success:^(NSURL * _Nullable imageURL, HXPhotoModel * _Nullable model, NSDictionary * _Nullable info) {
  1802. weakSelf.imageURL = imageURL;
  1803. if (success) {
  1804. success(imageURL, HXPhotoModelMediaSubTypePhoto, NO, weakSelf);
  1805. }
  1806. } failed:^(NSDictionary * _Nullable info, HXPhotoModel * _Nullable model) {
  1807. if (failed) {
  1808. failed(nil, weakSelf);
  1809. }
  1810. }];
  1811. return;
  1812. }
  1813. [weakSelf getImageURLWithImageData:imageData success:^(NSURL * _Nullable imageURL, HXPhotoModel * _Nullable model, NSDictionary * _Nullable info) {
  1814. weakSelf.imageURL = imageURL;
  1815. if (success) {
  1816. success(imageURL, HXPhotoModelMediaSubTypePhoto, NO, weakSelf);
  1817. }
  1818. } failed:^(NSDictionary * _Nullable info, HXPhotoModel * _Nullable model) {
  1819. if (failed) {
  1820. failed(nil, weakSelf);
  1821. }
  1822. }];
  1823. } failed:^(NSDictionary * _Nullable info, HXPhotoModel * _Nullable model) {
  1824. if (failed) {
  1825. failed(nil, weakSelf);
  1826. }
  1827. }];
  1828. // [self requestImageURLStartRequestICloud:nil progressHandler:nil success:^(NSURL * _Nullable imageURL, HXPhotoModel * _Nullable model, NSDictionary * _Nullable info) {
  1829. // if (success) {
  1830. // success(imageURL, HXPhotoModelMediaSubTypePhoto, NO, weakSelf);
  1831. // }
  1832. // } failed:^(NSDictionary * _Nullable info, HXPhotoModel * _Nullable model) {
  1833. // if (failed) {
  1834. // failed(nil, weakSelf);
  1835. // }
  1836. // }];
  1837. }
  1838. }else if (self.subType == HXPhotoModelMediaSubTypeVideo) {
  1839. if (self.type == HXPhotoModelMediaTypeCameraVideo) {
  1840. if (self.cameraVideoType == HXPhotoModelMediaTypeCameraVideoTypeLocal) {
  1841. if (success) {
  1842. success(self.videoURL, HXPhotoModelMediaSubTypeVideo, NO, self);
  1843. }
  1844. }else if (self.cameraVideoType == HXPhotoModelMediaTypeCameraVideoTypeNetWork) {
  1845. if (success) {
  1846. success(self.videoURL, HXPhotoModelMediaSubTypeVideo, YES, self);
  1847. }
  1848. }
  1849. }else {
  1850. [self exportVideoWithPresetName:presetName startRequestICloud:nil iCloudProgressHandler:nil exportProgressHandler:nil success:^(NSURL * _Nullable videoURL, HXPhotoModel * _Nullable model) {
  1851. if (success) {
  1852. success(videoURL, HXPhotoModelMediaSubTypeVideo, NO, weakSelf);
  1853. }
  1854. } failed:^(NSDictionary * _Nullable info, HXPhotoModel * _Nullable model) {
  1855. if (failed) {
  1856. failed(nil, weakSelf);
  1857. }
  1858. }];
  1859. }
  1860. }
  1861. }
  1862. - (void)getVideoURLWithSuccess:(HXModelURLHandler _Nullable)success
  1863. failed:(HXModelFailedBlock _Nullable)failed {
  1864. if (self.subType == HXPhotoModelMediaSubTypeVideo) {
  1865. if (self.type == HXPhotoModelMediaTypeCameraVideo) {
  1866. if (self.cameraVideoType == HXPhotoModelMediaTypeCameraVideoTypeLocal) {
  1867. if (success) {
  1868. success(self.videoURL, HXPhotoModelMediaSubTypeVideo, NO, self);
  1869. }
  1870. }else if (self.cameraVideoType == HXPhotoModelMediaTypeCameraVideoTypeNetWork) {
  1871. if (success) {
  1872. success(self.videoURL, HXPhotoModelMediaSubTypeVideo, YES, self);
  1873. }
  1874. }
  1875. }else {
  1876. [HXAssetManager requestVideoURL:self.asset completion:^(NSURL * _Nullable videoURL) {
  1877. __strong typeof(self) strongSelf = self;
  1878. if (videoURL) {
  1879. if (success) {
  1880. success(videoURL, HXPhotoModelMediaSubTypeVideo, NO, strongSelf);
  1881. }
  1882. }else {
  1883. if (failed) {
  1884. failed(nil, strongSelf);
  1885. }
  1886. }
  1887. }];
  1888. }
  1889. }else {
  1890. if (failed) {
  1891. failed(nil, self);
  1892. }
  1893. }
  1894. }
  1895. - (void)getImageURLWithResultHandler:(void (^ _Nullable)(HXAssetURLResult * _Nullable, HXPhotoModel *))resultHandler {
  1896. if (self.subType != HXPhotoModelMediaSubTypePhoto) {
  1897. if (resultHandler) {
  1898. resultHandler(nil, self);
  1899. }
  1900. return;
  1901. }
  1902. HXWeakSelf
  1903. if (self.photoEdit) {
  1904. [self getCameraImageURLWithSuccess:^(NSURL * _Nullable imageURL, HXPhotoModel * _Nullable model, NSDictionary * _Nullable info) {
  1905. HXAssetURLResult *result = [[HXAssetURLResult alloc] initWithUrl:imageURL urlType:HXAssetURLTypeLocal mediaType:HXPhotoModelMediaSubTypePhoto];
  1906. if (resultHandler) {
  1907. resultHandler(result, weakSelf);
  1908. }
  1909. } failed:^(NSDictionary * _Nullable info, HXPhotoModel * _Nullable model) {
  1910. if (resultHandler) {
  1911. resultHandler(nil, weakSelf);
  1912. }
  1913. }];
  1914. return;
  1915. }
  1916. if (self.type == HXPhotoModelMediaTypeCameraPhoto) {
  1917. if (self.cameraPhotoType == HXPhotoModelMediaTypeCameraPhotoTypeNetWork ||
  1918. self.cameraPhotoType == HXPhotoModelMediaTypeCameraPhotoTypeNetWorkGif) {
  1919. HXAssetURLResult *result = [[HXAssetURLResult alloc] initWithUrl:self.networkPhotoUrl urlType:HXAssetURLTypeNetwork mediaType:HXPhotoModelMediaSubTypePhoto];
  1920. if (resultHandler) {
  1921. resultHandler(result, self);
  1922. }
  1923. }else {
  1924. [self getCameraImageURLWithSuccess:^(NSURL * _Nullable imageURL, HXPhotoModel * _Nullable model, NSDictionary * _Nullable info) {
  1925. HXAssetURLResult *result = [[HXAssetURLResult alloc] initWithUrl:imageURL urlType:HXAssetURLTypeLocal mediaType:HXPhotoModelMediaSubTypePhoto];
  1926. if (resultHandler) {
  1927. resultHandler(result, weakSelf);
  1928. }
  1929. } failed:^(NSDictionary * _Nullable info, HXPhotoModel * _Nullable model) {
  1930. if (resultHandler) {
  1931. resultHandler(nil, weakSelf);
  1932. }
  1933. }];
  1934. }
  1935. return;
  1936. }
  1937. [self requestImageDataStartRequestICloud:nil progressHandler:nil success:^(NSData * _Nullable imageData, UIImageOrientation orientation, HXPhotoModel * _Nullable model, NSDictionary * _Nullable info) {
  1938. if (model.type == HXPhotoModelMediaTypePhotoGif) {
  1939. dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
  1940. NSString *fileName = [[NSString hx_fileName] stringByAppendingString:@".gif"];
  1941. NSString *fullPathToFile = [NSTemporaryDirectory() stringByAppendingPathComponent:fileName];
  1942. NSURL *imageURL = [weakSelf writeWithImageData:imageData toFile:fullPathToFile];
  1943. dispatch_async(dispatch_get_main_queue(), ^{
  1944. if (imageURL != nil) {
  1945. weakSelf.imageURL = imageURL;
  1946. HXAssetURLResult *result = [[HXAssetURLResult alloc] initWithUrl:imageURL urlType:HXAssetURLTypeLocal mediaType:HXPhotoModelMediaSubTypePhoto];
  1947. if (resultHandler) {
  1948. resultHandler(result, weakSelf);
  1949. }
  1950. }else {
  1951. if (resultHandler) {
  1952. resultHandler(nil, weakSelf);
  1953. }
  1954. }
  1955. });
  1956. });
  1957. return;
  1958. }
  1959. if (orientation != UIImageOrientationUp) {
  1960. UIImage *image = [[[UIImage alloc] initWithData:imageData] hx_normalizedImage];
  1961. [weakSelf getImageURLWithImage:image success:^(NSURL * _Nullable imageURL, HXPhotoModel * _Nullable model, NSDictionary * _Nullable info) {
  1962. weakSelf.imageURL = imageURL;
  1963. HXAssetURLResult *result = [[HXAssetURLResult alloc] initWithUrl:imageURL urlType:HXAssetURLTypeLocal mediaType:HXPhotoModelMediaSubTypePhoto];
  1964. if (resultHandler) {
  1965. resultHandler(result, weakSelf);
  1966. }
  1967. } failed:^(NSDictionary * _Nullable info, HXPhotoModel * _Nullable model) {
  1968. if (resultHandler) {
  1969. resultHandler(nil, weakSelf);
  1970. }
  1971. }];
  1972. return;
  1973. }
  1974. [weakSelf getImageURLWithImageData:imageData success:^(NSURL * _Nullable imageURL, HXPhotoModel * _Nullable model, NSDictionary * _Nullable info) {
  1975. weakSelf.imageURL = imageURL;
  1976. HXAssetURLResult *result = [[HXAssetURLResult alloc] initWithUrl:imageURL urlType:HXAssetURLTypeLocal mediaType:HXPhotoModelMediaSubTypePhoto];
  1977. if (resultHandler) {
  1978. resultHandler(result, weakSelf);
  1979. }
  1980. } failed:^(NSDictionary * _Nullable info, HXPhotoModel * _Nullable model) {
  1981. if (resultHandler) {
  1982. resultHandler(nil, weakSelf);
  1983. }
  1984. }];
  1985. } failed:^(NSDictionary * _Nullable info, HXPhotoModel * _Nullable model) {
  1986. if (resultHandler) {
  1987. resultHandler(nil, weakSelf);
  1988. }
  1989. }];
  1990. }
  1991. - (void)getVideoURLWithExportPreset:(HXVideoExportPreset)exportPreset
  1992. videoQuality:(NSInteger)videoQuality
  1993. resultHandler:(void (^ _Nullable)(HXAssetURLResult * _Nullable, HXPhotoModel *))resultHandler {
  1994. if (self.subType != HXPhotoModelMediaSubTypeVideo) {
  1995. if (resultHandler) {
  1996. resultHandler(nil, self);
  1997. }
  1998. return;
  1999. }
  2000. if (self.type == HXPhotoModelMediaTypeCameraVideo) {
  2001. if (self.cameraVideoType == HXPhotoModelMediaTypeCameraVideoTypeLocal) {
  2002. HXAssetURLResult *result = [[HXAssetURLResult alloc] initWithUrl:self.videoURL urlType:HXAssetURLTypeLocal mediaType:HXPhotoModelMediaSubTypeVideo];
  2003. if (resultHandler) {
  2004. resultHandler(result, self);
  2005. }
  2006. }else if (self.cameraVideoType == HXPhotoModelMediaTypeCameraVideoTypeNetWork) {
  2007. HXAssetURLResult *result = [[HXAssetURLResult alloc] initWithUrl:self.videoURL urlType:HXAssetURLTypeNetwork mediaType:HXPhotoModelMediaSubTypeVideo];
  2008. if (resultHandler) {
  2009. resultHandler(result, self);
  2010. }
  2011. }
  2012. return;
  2013. }
  2014. if (exportPreset == HXVideoExportPresetRatio_Original) {
  2015. [HXAssetManager requestVideoURL:self.asset completion:^(NSURL * _Nullable videoURL) {
  2016. __strong typeof(self) strongSelf = self;
  2017. if (videoURL) {
  2018. HXAssetURLResult *result = [[HXAssetURLResult alloc] initWithUrl:videoURL urlType:HXAssetURLTypeLocal mediaType:HXPhotoModelMediaSubTypeVideo];
  2019. if (resultHandler) {
  2020. resultHandler(result, strongSelf);
  2021. }
  2022. }else {
  2023. if (resultHandler) {
  2024. resultHandler(nil, strongSelf);
  2025. }
  2026. }
  2027. }];
  2028. }else {
  2029. [HXAssetManager requestVideoURLForAsset:self.asset
  2030. toFile:nil
  2031. exportPreset:exportPreset videoQuality:videoQuality
  2032. resultHandler:^(NSURL * _Nullable videoURL) {
  2033. __strong typeof(self) strongSelf = self;
  2034. if (videoURL) {
  2035. HXAssetURLResult *result = [[HXAssetURLResult alloc] initWithUrl:videoURL urlType:HXAssetURLTypeLocal mediaType:HXPhotoModelMediaSubTypeVideo];
  2036. if (resultHandler) {
  2037. resultHandler(result, strongSelf);
  2038. }
  2039. }else {
  2040. if (resultHandler) {
  2041. resultHandler(nil, strongSelf);
  2042. }
  2043. }
  2044. }];
  2045. }
  2046. }
  2047. @end