簡(jiǎn)介(當(dāng)前版本:1.11.4)
一個(gè)專(zhuān)門(mén)裁剪圖片、GIF各墨、視頻的輪子指孤,簡(jiǎn)單易用,功能豐富(高自由度的參數(shù)設(shè)定贬堵、支持旋轉(zhuǎn)和鏡像翻轉(zhuǎn)恃轩、蒙版、壓縮等)黎做,能滿(mǎn)足絕大部分裁剪的需求叉跛。
Feature:
? 能自適應(yīng)裁剪區(qū)域的縮放;
? 高自由度的參數(shù)設(shè)定蒸殿,包括裁剪區(qū)域的間距筷厘、裁剪寬高比、是否自適應(yīng)縮放等宏所;
? 支持最多8個(gè)拖拽方向的裁剪區(qū)域酥艳;
? 支持上左下右的旋轉(zhuǎn);
? 水平和垂直的鏡像翻轉(zhuǎn)爬骤;
? 兩種邊框樣式充石;
? 支持圓框裁剪;
? 自定義毛玻璃樣式盖腕、邊框顏色赫冬、背景顏色、遮罩透明度溃列;
? 自定義邊框圖片;
? 可動(dòng)態(tài)修改視圖區(qū)域和裁剪區(qū)域間距劲厌,支持橫豎屏切換;
? 可自定義蒙版圖片裁剪;
? 可裁剪本地視頻整段畫(huà)面或某一幀畫(huà)面听隐;
? 可截取某一段本地視頻补鼻,裁剪后并轉(zhuǎn)成GIF;
? 可裁剪GIF雅任;
? 可保存當(dāng)前裁剪狀態(tài)风范;
? 圖片支持N宮格裁剪;
? 兼容Swift&SwiftUI環(huán)境沪么。
TODO:
?? Swift版本硼婿;
?? 固定不縮放裁剪區(qū)域;
?? 視頻不再需要修正方向再裁剪禽车;
?? 裁剪遠(yuǎn)程視頻寇漫;
?? 持久化緩存裁剪歷史刊殉;
?? 將視頻裁剪部分(AVFoundation模塊)分離出來(lái);
?? 實(shí)現(xiàn)蘋(píng)果相冊(cè)裁剪功能中的自由拖拽旋轉(zhuǎn)州胳、翻轉(zhuǎn)角度的效果记焊。
注意:由于autoLayout不利于手勢(shì)控制,所以目前使用的是frame布局栓撞,暫不支持autoLayout遍膜。
最新改動(dòng)
兼容Swift&SwiftUI環(huán)境。
如何使用
初始化
1. 配置初始參數(shù)
可設(shè)置的裁剪元素(圖片瓤湘、GIF瓢颅、視頻),只能選擇其中一個(gè)岭粤,并且不能為nil:
- image:裁剪的圖片/GIF(以UIImage傳入)
- imageData:裁剪的圖片/GIF(以NSData傳入)
- videoURL:裁剪的本地視頻(以NSURL傳入)
- videoAsset:裁剪的本地視頻(以AVURLAsset傳入)
其他部分可配置參數(shù)(更多可查看JPImageresizerView的頭文件):
- blurEffect:毛玻璃樣式
- borderImage:邊框圖片
- frameType & strokeColor:邊框樣式&顏色
- bgColor:背景色
- maskAlpha:遮罩透明度
- resizeWHScale:裁剪的寬高比
- contentInsets:裁剪區(qū)域與視圖的間距
- maskImage:蒙版圖片
圖片/GIF
//【裁剪的圖片/GIF】以UIImage傳入
JPImageresizerConfigure *configure = [JPImageresizerConfigure defaultConfigureWithImage:image make:^(JPImageresizerConfigure *configure) {
// 到這里已經(jīng)有了默認(rèn)參數(shù)值惜索,可以在這里另外設(shè)置你想要的參數(shù)值(使用了鏈?zhǔn)骄幊谭绞剑? configure
.jp_maskAlpha(0.5)
.jp_strokeColor([UIColor yellowColor])
.jp_frameType(JPClassicFrameType)
.jp_contentInsets(contentInsets)
.jp_bgColor([UIColor orangeColor])
.jp_isClockwiseRotation(YES)
.jp_animationCurve(JPAnimationCurveEaseOut);
}];
// 如果想要初始化為正方形,可設(shè)置 JPImageresizerConfigure 的 resizeWHScale 屬性
configure.resizeWHScale = 1; // 默認(rèn)為0剃浇,完全顯示
// 另外如果還需要固定比例的話(huà):
configure.isArbitrarily = YES; // 默認(rèn)為YES
// 2.【裁剪的圖片/GIF】以NSData傳入
JPImageresizerConfigure *configure = [JPImageresizerConfigure defaultConfigureWithImageData:imageData make:^(JPImageresizerConfigure *configure) { ...... };
視頻
關(guān)于從系統(tǒng)相冊(cè)獲取的視頻巾兆,視頻方向有可能是修改過(guò)的(即相冊(cè)中旋轉(zhuǎn)、翻轉(zhuǎn)過(guò))虎囚,修改后的videoTrack.preferredTransform != CGAffineTransformIdentity
角塑,圖片也會(huì),不過(guò)好歹圖片有個(gè)imageOrientation
屬性告知具體改動(dòng)了什么淘讥,由于我才疏學(xué)淺圃伶,單單從preferredTransform
并不知道是經(jīng)過(guò)了具體的哪些改動(dòng),如果只是旋轉(zhuǎn)還好蒲列,旋轉(zhuǎn)+翻轉(zhuǎn)后的數(shù)值都是不一定的窒朋,這樣導(dǎo)致最后裁剪時(shí)會(huì)錯(cuò)亂,目前只好先修正方向后再進(jìn)行裁剪蝗岖,日后改進(jìn)侥猩,希望能有緣之士給予指點(diǎn)!
初始化后再修正(先進(jìn)入頁(yè)面后再修正)抵赢,具體操作可參照Demo:
// 1.【視頻】以NSURL傳入
JPImageresizerConfigure *configure = [JPImageresizerConfigure defaultConfigureWithVideoURL:videoURL make:^(JPImageresizerConfigure *configure) { ...... } fixErrorBlock:^(NSURL *cacheURL, JPImageresizerErrorReason reason) {
// 初始化修正視頻方向的錯(cuò)誤回調(diào)
} fixStartBlock:^{
// 初始化修正視頻方向的開(kāi)始回調(diào)
} fixProgressBlock:^(float progress) {
// 初始化修正視頻方向的進(jìn)度回調(diào)
} fixCompleteBlock:^(NSURL *cacheURL) {
// 初始化修正視頻方向的完成回調(diào)
}];
// 2.【視頻】以AVURLAsset傳入
[JPImageresizerConfigure defaultConfigureWithVideoAsset:videoAsset
make:^(JPImageresizerConfigure *configure) { ...... }
fixErrorBlock:^(NSURL *cacheURL, JPImageresizerErrorReason reason) { ...... }
fixStartBlock:^{ ...... } fixProgressBlock:^(float progress) { ...... }
fixCompleteBlock:^(NSURL *cacheURL) { ...... }];
又或者先修正再初始化(先修正后再進(jìn)入頁(yè)面)欺劳,可以使用JPImageresizerTool
的API來(lái)修正,具體操作可參照Demo:
// 獲取視頻信息
AVURLAsset *videoAsset = [AVURLAsset assetWithURL:videoURL];
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
[videoAsset loadValuesAsynchronouslyForKeys:@[@"duration", @"tracks"] completionHandler:^{
dispatch_semaphore_signal(semaphore);
}];
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
AVAssetTrack *videoTrack = [videoAsset tracksWithMediaType:AVMediaTypeVideo].firstObject;
if (CGAffineTransformEqualToTransform(videoTrack.preferredTransform, CGAffineTransformIdentity)) {
// 無(wú)需修正铅鲤,進(jìn)入裁剪界面
JPImageresizerConfigure *configure = [JPImageresizerConfigure defaultConfigureWithVideoAsset:videoAsset make:nil fixErrorBlock:nil fixStartBlock:nil fixProgressBlock:nil fixCompleteBlock:nil];
......
return;
}
// 修正方向
[JPImageresizerTool fixOrientationVideoWithAsset:videoAsset fixErrorBlock:^(NSURL *cacheURL, JPImageresizerErrorReason reason) {
// 修正視頻方向的錯(cuò)誤回調(diào)
} fixStartBlock:^(AVAssetExportSession *exportSession) {
// 修正視頻方向的開(kāi)始回調(diào)
// 返回exportSession划提,可監(jiān)聽(tīng)進(jìn)度或取消導(dǎo)出
} fixCompleteBlock:^(NSURL *cacheURL) {
// 修正視頻方向的完成回調(diào)
// cacheURL:修正方向后的視頻導(dǎo)出后的最終存放路徑,默認(rèn)該路徑為NSTemporaryDirectory文件夾下邢享,保存該路徑鹏往,裁剪后刪除視頻。
// 開(kāi)始裁剪骇塘,進(jìn)入裁剪界面
JPImageresizerConfigure *configure = [JPImageresizerConfigure defaultConfigureWithVideoAsset:[AVURLAsset assetWithURL:cacheURL] make:nil fixErrorBlock:nil fixStartBlock:nil fixProgressBlock:nil fixCompleteBlock:nil];
......
}];
- PS1:如果視頻不需要修正掸犬,
fixStartBlock
袜漩、fixProgressBlock
、fixErrorBlock
均不會(huì)調(diào)用湾碎,會(huì)直接調(diào)用fixCompleteBlock
蜻拨,返回原路徑辕近; - PS2:如果確定是無(wú)需修正方向的視頻,
fixErrorBlock
曲聂、fixStartBlock
递惋、fixProgressBlock
柔滔、fixCompleteBlock
傳nil
; - PS3:更換視頻:
-setVideoURL: animated: fixErrorBlock: fixStartBlock: fixProgressBlock: fixCompleteBlock:
和-setVideoAsset: animated: fixErrorBlock: fixStartBlock: fixProgressBlock: fixCompleteBlock:
方法也與之同理萍虽,內(nèi)部會(huì)判定是否需要修正睛廊; - PS4:如果需要初始化就固定裁剪寬高比(如圓切、蒙版等)杉编,需要設(shè)置
JPImageresizerConfigure
的isArbitrarily
屬性為NO(默認(rèn)為YES):
JPImageresizerConfigure *configure = [JPImageresizerConfigure darkBlurMaskTypeConfigureWithImage:nil make:^(JPImageresizerConfigure *configure) {
configure
.jp_maskImage([UIImage imageNamed:@"love.png"])
.jp_isArbitrarily(NO);
}];
2. 創(chuàng)建JPImageresizerView對(duì)象并添加到視圖上
JPImageresizerView *imageresizerView = [JPImageresizerView imageresizerViewWithConfigure:configure imageresizerIsCanRecovery:^(BOOL isCanRecovery) {
// 可在這里監(jiān)聽(tīng)到是否可以重置
// 如果不需要重置(isCanRecovery為NO)超全,可在這里做相應(yīng)處理,例如將重置按鈕設(shè)置為不可點(diǎn)或隱藏
// PS:isCanRecovery僅針對(duì)[旋轉(zhuǎn)]邓馒、[縮放]嘶朱、[鏡像]的變化情況,其他如裁剪寬高比光酣、圓切等變化情況需用戶(hù)自行判定能否重置
// 具體操作可參照Demo
// 注意循環(huán)引用
} imageresizerIsPrepareToScale:^(BOOL isPrepareToScale) {
// 可在這里監(jiān)聽(tīng)到裁剪區(qū)域是否預(yù)備縮放至適合范圍
// 如果預(yù)備縮放(isPrepareToScale為YES)疏遏,此時(shí)裁剪、旋轉(zhuǎn)救军、鏡像功能不可用财异,可在這里做相應(yīng)處理,例如將對(duì)應(yīng)按鈕設(shè)置為不可點(diǎn)或隱藏
// 具體操作可參照Demo
// 注意循環(huán)引用
}];
[self.view addSubview:imageresizerView];
self.imageresizerView = imageresizerView;
// 創(chuàng)建后均可動(dòng)態(tài)修改configure的參數(shù)
self.imageresizerView.image = [UIImage imageNamed:@"Kobe.jpg"]; // 更換裁剪圖片(默認(rèn)帶動(dòng)畫(huà)效果)
self.imageresizerView.resizeWHScale = 16.0 / 9.0; // 修改裁剪寬高比
self.imageresizerView.initialResizeWHScale = 0.0; // 默認(rèn)為初始化時(shí)的resizeWHScale唱遭,調(diào)用 -recoveryByInitialResizeWHScale 方法進(jìn)行重置則 resizeWHScale 會(huì)重置為該屬性的值
// 注意:iOS11以下的系統(tǒng)戳寸,所在的controller最好設(shè)置automaticallyAdjustsScrollViewInsets為NO
// 不然imageresizerView會(huì)隨導(dǎo)航欄或狀態(tài)欄的變化產(chǎn)生偏移
if (@available(iOS 11.0, *)) {
} else {
self.automaticallyAdjustsScrollViewInsets = NO;
}
在Swift中的使用
// 1.初始配置
let configure = JPImageresizerConfigure.defaultConfigure(with: image) { c in
_ = c
.jp_viewFrame(frame)
.jp_bgColor(.black)
.jp_frameType(.classicFrameType)
.jp_contentInsets(.init(top: 16, left: 16, bottom: 16, right: 16))
.jp_animationCurve(.easeInOut)
}
// 2.創(chuàng)建imageresizerView
let imageresizerView = JPImageresizerView(configure: configure) { [weak self] isCanRecovery in
// 當(dāng)不需要重置設(shè)置按鈕不可點(diǎn)
self?.recoveryBtn.isEnabled = isCanRecovery
} imageresizerIsPrepareToScale: { [weak self] isPrepareToScale in
// 當(dāng)預(yù)備縮放設(shè)置按鈕不可點(diǎn),結(jié)束后可點(diǎn)擊
self?.operationView.isUserInteractionEnabled = !isPrepareToScale
}
// 3.添加到視圖上
view.insertSubview(imageresizerView, at: 0)
self.imageresizerView = imageresizerView
具體使用可以去Github下載Demo查看(JPCropViewController)胆萧。
裁剪
裁剪說(shuō)明:
1.裁剪過(guò)程是在子線(xiàn)程中執(zhí)行庆揩,進(jìn)度、錯(cuò)誤跌穗、完成的回調(diào)都會(huì)切回主線(xiàn)程執(zhí)行订晌,如果是高清圖片,裁剪前可添加HUD提示蚌吸;
2.compressScale:圖片和GIF的壓縮比例锈拨,大于等于1按原圖尺寸裁剪,小于等于0則返回nil(例:compressScale = 0.5羹唠,1000 x 500 --> 500 x 250)奕枢;
3.cacheURL:緩存路徑娄昆,可設(shè)置為nil,圖片和GIF則不緩存缝彬,而視頻會(huì)默認(rèn)緩存到系統(tǒng)的NSTemporaryDirectory文件夾下萌焰,視頻名為當(dāng)前時(shí)間戳,格式為mp4谷浅;
4.錯(cuò)誤原因 JPCropErrorReason 說(shuō)明:
- JPCEReason_NilObject:裁剪元素為空
- JPCEReason_CacheURLAlreadyExists:緩存路徑已存在其他文件
- JPCEReason_NoSupportedFileType:不支持的文件類(lèi)型
- JPCEReason_VideoAlreadyDamage:視頻文件已損壞
- JPCEReason_VideoExportFailed:視頻導(dǎo)出失敗
- JPCEReason_VideoExportCancelled:視頻導(dǎo)出取消
5.注意:緩存路徑的圖片格式會(huì)自動(dòng)修正扒俯,例如原本寫(xiě)的是`xxx/xxx.jpeg`,由于使用了蒙版一疯,裁剪后則會(huì)修正為`xxx/xxx.png`了撼玄,最終的緩存路徑要以裁剪回調(diào)`completeBlock`中的`result.cacheURL`為準(zhǔn)。
裁剪圖片
// 1.以原圖尺寸進(jìn)行裁剪
[self.imageresizerView cropPictureWithCacheURL:cacheURL errorBlock:^(NSURL *cacheURL, JPImageresizerErrorReason reason) {
// 錯(cuò)誤的回調(diào)
// reason:錯(cuò)誤原因
// 注意循環(huán)引用
} completeBlock:^(JPImageresizerResult *result) {
// 裁剪完成
// result:裁剪后的結(jié)果(JPImageresizerResult)
// result.image:裁剪后的圖片(已解碼好的)
// result.cacheURL:目標(biāo)存放路徑
// result.isCacheSuccess:是否緩存成功(緩存不成功則cacheURL為nil)
// 注意循環(huán)引用
}];
// 2.自定義壓縮比例裁剪圖片
// compressScale --- 壓縮比例墩邀,大于等于1按原圖尺寸裁剪掌猛,小于等于0則返回nil(例:compressScale = 0.5,1000 x 500 --> 500 x 250)
// completeBlock --- 裁剪完成的回調(diào)(返回裁剪后的結(jié)果眉睹,包含已解碼好的圖片荔茬、緩存路徑)
- (void)cropPictureWithCompressScale:(CGFloat)compressScale
cacheURL:(NSURL *)cacheURL
errorBlock:(JPImageresizerErrorBlock)errorBlock
completeBlock:(JPCropDoneBlock)completeBlock;
- 裁剪N宮格圖片
// 1.自定義N宮格裁剪
// columnCount:N宮格的列數(shù)(最小1列)
// rowCount:N宮格的行數(shù)(最小1行)
// compressScale --- 壓縮比例,大于等于1按原圖尺寸裁剪辣往,小于等于0則返回nil(例:compressScale = 0.5兔院,1000 x 500 --> 500 x 250)
// bgColor --- N宮格的背景色(如果圖片有透明區(qū)域,或者設(shè)置了蒙版的情況才生效站削,設(shè)置隱藏(透明)區(qū)域的背景色)
[self.imageresizerView cropGirdPicturesWithColumnCount:4 rowCount:2 compressScale:1 bgColor:UIColor.redColor cacheURL:cacheURL errorBlock:^(NSURL *cacheURL, JPImageresizerErrorReason reason) {
// 錯(cuò)誤的回調(diào)
// reason:錯(cuò)誤原因
// 注意循環(huán)引用
} completeBlock:^(JPImageresizerResult *originResult, NSArray<JPImageresizerResult *> *fragmentResults, NSInteger columnCount, NSInteger rowCount) {
// 裁剪完成
// originResult:裁剪后的原圖結(jié)果(開(kāi)始N宮格之前)
// fragmentResults:裁剪后的原圖被裁剪成N宮格圖片的結(jié)果集合(共 columnCount * rowCount 個(gè))
// columnCount:調(diào)用該方法時(shí)傳入的列數(shù)
// rowCount:調(diào)用該方法時(shí)傳入的行數(shù)
// 注意循環(huán)引用
}];
// 2.九宮格裁剪(3行3列)
- (void)cropNineGirdPicturesWithCompressScale:(CGFloat)compressScale
bgColor:(UIColor *)bgColor
cacheURL:(NSURL *)cacheURL
errorBlock:(JPImageresizerErrorBlock)errorBlock
completeBlock:(JPCropNGirdDoneBlock)completeBlock;
分享至朋友圈(建議使用resizeWHScale = 1
進(jìn)行裁剪):
裁剪GIF
// 1.原圖尺寸裁剪GIF
[self.imageresizerView cropGIFWithCacheURL:cacheURL errorBlock:^(NSURL *cacheURL, JPImageresizerErrorReason reason) {
// 錯(cuò)誤的回調(diào)
// reason:錯(cuò)誤原因
// 注意循環(huán)引用
} completeBlock:^(JPImageresizerResult *result) {
// 裁剪完成
// result:裁剪后的結(jié)果(JPImageresizerResult)
// result.image:裁剪后的GIF(已解碼好的)
// result.cacheURL:目標(biāo)存放路徑
// result.isCacheSuccess:是否緩存成功(緩存不成功則cacheURL為nil)
// 注意循環(huán)引用
}];
// 2.自定義壓縮比例裁剪GIF
// completeBlock --- 裁剪完成的回調(diào)(返回裁剪后的結(jié)果坊萝,包含已解碼好的GIF、緩存路徑)
- (void)cropGIFWithCompressScale:(CGFloat)compressScale
cacheURL:(NSURL *)cacheURL
errorBlock:(JPImageresizerErrorBlock)errorBlock
completeBlock:(JPCropDoneBlock)completeBlock;
// 3.自定義裁剪GIF
// isReverseOrder --- 是否倒放
// rate --- 速率
// completeBlock --- 裁剪完成的回調(diào)(返回裁剪后的結(jié)果许起,包含已解碼好的GIF十偶、緩存路徑)
- (void)cropGIFWithCompressScale:(CGFloat)compressScale
isReverseOrder:(BOOL)isReverseOrder
rate:(float)rate
cacheURL:(NSURL *)cacheURL
errorBlock:(JPImageresizerErrorBlock)errorBlock
completeBlock:(JPCropDoneBlock)completeBlock;
裁剪GIF的其中一幀
// 1.原圖尺寸裁剪GIF當(dāng)前幀畫(huà)面
// completeBlock --- 裁剪完成的回調(diào)(返回裁剪后的結(jié)果,包含已解碼好的圖片园细、緩存路徑)
- (void)cropGIFCurrentIndexWithCacheURL:(NSURL *)cacheURL
errorBlock:(JPImageresizerErrorBlock)errorBlock
completeBlock:(JPCropDoneBlock)completeBlock;
// 2.自定義壓縮比例裁剪GIF當(dāng)前幀畫(huà)面
// completeBlock --- 裁剪完成的回調(diào)(返回裁剪后的結(jié)果惦积,包含已解碼好的圖片、緩存路徑)
- (void)cropGIFCurrentIndexWithCompressScale:(CGFloat)compressScale
cacheURL:(NSURL *)cacheURL
errorBlock:(JPImageresizerErrorBlock)errorBlock
completeBlock:(JPCropDoneBlock)completeBlock;
// 3.自定義壓縮比例裁剪GIF指定幀畫(huà)面
// index --- 第幾幀畫(huà)面
// compressScale --- 壓縮比例猛频,大于等于1按原圖尺寸裁剪狮崩,小于等于0則返回nil(例:compressScale = 0.5,1000 x 500 --> 500 x 250)
- (void)cropGIFWithIndex:(NSUInteger)index
compressScale:(CGFloat)compressScale
cacheURL:(NSURL *)cacheURL
errorBlock:(JPImageresizerErrorBlock)errorBlock
completeBlock:(JPCropDoneBlock)completeBlock;
- PS:可以設(shè)置isLoopPlaybackGIF自主選擇裁剪哪一幀(默認(rèn)為NO鹿寻,設(shè)置為YES會(huì)自動(dòng)播放GIF)
self.imageresizerView.isLoopPlaybackGIF = NO;
裁剪本地視頻
- PS:目前只針對(duì)本地視頻睦柴,遠(yuǎn)程視頻暫未適配。
// 裁剪整段視頻
// cacheURL:如果為nil毡熏,會(huì)默認(rèn)緩存到系統(tǒng)的NSTemporaryDirectory文件夾下坦敌,視頻名為當(dāng)前時(shí)間戳,格式為mp4
[self.imageresizerView cropVideoWithCacheURL:cacheURL errorBlock:^(NSURL *cacheURL, JPCropErrorReason reason) {
// 錯(cuò)誤的回調(diào)
// reason:錯(cuò)誤原因
// 注意循環(huán)引用
} progressBlock:^(float progress) {
// 監(jiān)聽(tīng)進(jìn)度
// progress:0~1
// 注意循環(huán)引用
} completeBlock:^(JPImageresizerResult *result) {
// 裁剪完成
// result:裁剪后的結(jié)果(JPImageresizerResult)
// result.cacheURL:目標(biāo)存放路徑,如果為nil狱窘,會(huì)默認(rèn)緩存到系統(tǒng)的NSTemporaryDirectory文件夾下杜顺,視頻名為當(dāng)前時(shí)間戳,格式為mp4
// result.isCacheSuccess:是否緩存成功(緩存不成功則cacheURL為nil)
// 注意循環(huán)引用
}];
// 可設(shè)置視頻導(dǎo)出質(zhì)量
// presetName --- 系統(tǒng)的視頻導(dǎo)出質(zhì)量蘸炸,如:AVAssetExportPresetLowQuality躬络,AVAssetExportPresetMediumQuality,AVAssetExportPresetHighestQuality等
- (void)cropVideoWithPresetName:(NSString *)presetName
cacheURL:(NSURL *)cacheURL
errorBlock:(JPCropErrorBlock)errorBlock
progressBlock:(JPExportVideoProgressBlock)progressBlock
completeBlock:(JPCropDoneBlock)completeBlock;
// 取消視頻導(dǎo)出
// 當(dāng)視頻正在導(dǎo)出時(shí)調(diào)用即可取消導(dǎo)出搭儒,觸發(fā)errorBlock回調(diào)(JPCEReason_ExportCancelled)
- (void)videoCancelExport;
- PS:由于視頻的寬高都必須是16的整數(shù)倍洗鸵,否則導(dǎo)出后系統(tǒng)會(huì)自動(dòng)對(duì)尺寸進(jìn)行校正,不足的地方會(huì)以綠邊的形式進(jìn)行填充仗嗦,因此我在方法內(nèi)部對(duì)裁剪尺寸做了對(duì)16除余的修改,所以最后導(dǎo)出視頻的寬高比有可能跟指定的寬高比有些許差異甘凭。
裁剪視頻的其中一幀
// 1.原圖尺寸裁剪視頻當(dāng)前幀畫(huà)面
// cacheURL --- 緩存路徑(可設(shè)置為nil稀拐,則不會(huì)緩存)
// completeBlock --- 裁剪完成的回調(diào)(返回裁剪后的結(jié)果,包含已解碼好的圖片丹弱、緩存路徑)
- (void)cropVideoCurrentFrameWithCacheURL:(NSURL *)cacheURL
errorBlock:(JPImageresizerErrorBlock)errorBlock
completeBlock:(JPCropDoneBlock)completeBlock;
// 2.自定義壓縮比例裁剪視頻當(dāng)前幀畫(huà)面
// cacheURL --- 緩存路徑(可設(shè)置為nil德撬,則不會(huì)緩存)
// completeBlock --- 裁剪完成的回調(diào)(返回裁剪后的結(jié)果,包含已解碼好的圖片躲胳、緩存路徑)
- (void)cropVideoCurrentFrameWithCompressScale:(CGFloat)compressScale
cacheURL:(NSURL *)cacheURL
errorBlock:(JPImageresizerErrorBlock)errorBlock
completeBlock:(JPCropDoneBlock)completeBlock;
// 3.自定義壓縮比例裁剪視頻指定幀畫(huà)面
// second --- 第幾秒畫(huà)面
// cacheURL --- 緩存路徑(可設(shè)置為nil蜓洪,則不會(huì)緩存)
// completeBlock --- 裁剪完成的回調(diào)(返回裁剪后的結(jié)果,包含已解碼好的圖片坯苹、緩存路徑)
- (void)cropVideoOneFrameWithSecond:(float)second
compressScale:(CGFloat)compressScale
cacheURL:(NSURL *)cacheURL
errorBlock:(JPImageresizerErrorBlock)errorBlock
completeBlock:(JPCropDoneBlock)completeBlock;
截取視頻某一段裁剪后轉(zhuǎn)GIF
// 1.視頻從當(dāng)前時(shí)間開(kāi)始截取指定秒數(shù)畫(huà)面轉(zhuǎn)GIF(fps = 10隆檀,rate = 1,maximumSize = 500 * 500)
// duration --- 截取多少秒
// completeBlock --- 裁剪完成的回調(diào)(返回裁剪后的結(jié)果粹湃,包含已解碼好的GIF恐仑、緩存路徑)
- (void)cropVideoToGIFFromCurrentSecondWithDuration:(NSTimeInterval)duration
cacheURL:(NSURL *)cacheURL
errorBlock:(JPImageresizerErrorBlock)errorBlock
completeBlock:(JPCropDoneBlock)completeBlock;
// 2.視頻自定義截取指定秒數(shù)畫(huà)面轉(zhuǎn)GIF
// duration --- 截取多少秒
// fps --- 幀率(設(shè)置為0則以視頻真身幀率)
// rate --- 速率
// maximumSize --- 截取的尺寸(設(shè)置為0則以視頻真身尺寸)
// completeBlock --- 裁剪完成的回調(diào)(返回裁剪后的結(jié)果,包含已解碼好的GIF为鳄、緩存路徑)
- (void)cropVideoToGIFFromStartSecond:(NSTimeInterval)startSecond
duration:(NSTimeInterval)duration
fps:(float)fps
rate:(float)rate
maximumSize:(CGSize)maximumSize
cacheURL:(NSURL *)cacheURL
errorBlock:(JPImageresizerErrorBlock)errorBlock
completeBlock:(JPCropDoneBlock)completeBlock;
- PS:裁剪整段視頻畫(huà)面圓切裳仆、蒙版的功能不能使用,目前只對(duì)圖片和GIF有效孤钦。
蒙版
// 設(shè)置蒙版圖片(目前僅支持png圖片)
self.imageresizerView.maskImage = [UIImage imageNamed:@"love.png"];
// 直接設(shè)置該值即是調(diào)用 -setMaskImage: isToBeArbitrarily: animated: 方法歧斟,其中默認(rèn) isToBeArbitrarily = (maskImage ? NO : self.isArbitrarily),isAnimated = YES
// 移除蒙版圖片
self.imageresizerView.maskImage = nil;
-
PS:如果使用了蒙版圖片偏形,那么最后裁剪出來(lái)的是png圖片静袖,因此裁剪后體積有可能會(huì)比原本的圖片更大。
圓切
// 設(shè)置圓切
// 設(shè)置后壳猜,resizeWHScale為1:1勾徽,半徑為寬高的一半,邊框的上、左喘帚、下畅姊、右的中部均可拖動(dòng)。
self.imageresizerView.isRoundResize = YES;
// 直接設(shè)置該值即是調(diào)用 -setIsRoundResize: isToBeArbitrarily: animated: 方法吹由,其中默認(rèn) isToBeArbitrarily = (isRoundResize ? NO : self.isArbitrarily)若未,isAnimated = YES
// 還原矩形
self.imageresizerView.isRoundResize = NO;
// 或者只需設(shè)置一下resizeWHScale為任意值即可
self.imageresizerView.resizeWHScale = 0.0;
橫豎屏切換
// 需要用戶(hù)去監(jiān)聽(tīng)橫豎屏的切換,或自己手動(dòng)切換時(shí)倾鲫,調(diào)用該方法刷新
// 1.updateFrame:刷新的Frame(例如橫豎屏切換粗合,傳入self.view.bounds即可)
// 2.contentInsets:裁剪區(qū)域與主視圖的內(nèi)邊距
// 3.duration:刷新時(shí)長(zhǎng)(大于0即帶有動(dòng)畫(huà)效果)
//【具體操作可參照Demo】
[self.imageresizerView updateFrame:self.view.bounds contentInsets:contentInsets duration:duration];
更改邊框樣式
// 目前只提供兩種邊框樣式,分別是簡(jiǎn)潔樣式JPConciseFrameType乌昔,和經(jīng)典樣式JPClassicFrameType
// 可在初始化或直接設(shè)置frameType屬性來(lái)修改邊框樣式
self.imageresizerView.frameType = JPClassicFrameType;
自定義邊框圖片
// 使用自定義邊框圖片(例:平鋪模式)
UIImage *tileBorderImage = [[UIImage imageNamed:@"jp_dotted_line"] resizableImageWithCapInsets:UIEdgeInsetsMake(14, 14, 14, 14) resizingMode:UIImageResizingModeTile];
// 設(shè)置邊框圖片與邊線(xiàn)的偏移量(即CGRectInset隙疚,用于調(diào)整邊框圖片與邊線(xiàn)的差距)
self.imageresizerView.borderImageRectInset = CGPointMake(-1.75, -1.75);
// 設(shè)置邊框圖片(若為nil則使用frameType的邊框)
self.imageresizerView.borderImage = tileBorderImage;
切換裁剪寬高比
- PS:設(shè)置裁剪寬高比會(huì)自動(dòng)移除圓切和蒙版
// 1.自定義參數(shù)切換
/**
* resizeWHScale: 目標(biāo)裁剪寬高比(0則為任意比例)
* isToBeArbitrarily:切換之后 resizeWHScale 是否為任意比例(若為YES,最后 resizeWHScale = 0)
* animated: 是否帶動(dòng)畫(huà)效果
*/
[self.imageresizerView setResizeWHScale:(16.0 / 9.0) isToBeArbitrarily:YES animated:YES];
// 2.直接切換
self.imageresizerView.resizeWHScale = 1.0;
// 默認(rèn)切換之后保存最新的 resizeWHScale磕道,且自帶動(dòng)畫(huà)效果供屉,如果設(shè)置為0,以當(dāng)前裁剪框的寬高比設(shè)置溺蕉,并且最后 isArbitrarily = YES伶丐,相當(dāng)于:
[self.imageresizerView setResizeWHScale:1.0 isToBeArbitrarily:(resizeWHScale <= 0) animated:YES];
// 是否可以任意比例拖拽(包括圓切、蒙版)
self.imageresizerView.isArbitrarily = !self.imageresizerView.isArbitrarily;
// 更多API可查看 JPImageresizerView.h 上的注釋
自定義毛玻璃樣式疯特、邊框顏色哗魂、背景顏色、遮罩透明度
// 設(shè)置毛玻璃樣式(默認(rèn)帶動(dòng)畫(huà)效果)
self.imageresizerView.blurEffect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleDark];
// 設(shè)置邊框顏色(默認(rèn)帶動(dòng)畫(huà)效果)
self.imageresizerView.strokeColor = UIColor.whiteColor;
// 設(shè)置背景顏色(默認(rèn)帶動(dòng)畫(huà)效果)
self.imageresizerView.bgColor = UIColor.blackColor;
// 設(shè)置遮罩透明度(默認(rèn)帶動(dòng)畫(huà)效果)
// PS:跟毛玻璃互斥漓雅,當(dāng)設(shè)置了毛玻璃則遮罩為透明
self.imageresizerView.maskAlpha = 0.5; // blurEffect = nil 才生效
// 一步設(shè)置毛玻璃樣式录别、邊框顏色、背景顏色故硅、遮罩透明度
[self.imageresizerView setupStrokeColor:strokeColor blurEffect:[UIBlurEffect effectWithStyle:UIBlurEffectStyleDark] bgColor:UIColor.blackColor maskAlpha: 0.5 animated:YES];
鏡像翻轉(zhuǎn)
// 垂直鏡像庶灿,YES->沿著Y軸旋轉(zhuǎn)180°,NO->還原
BOOL isVerticalityMirror = !self.imageresizerView.verticalityMirror;
[self.imageresizerView setVerticalityMirror:isVerticalityMirror animated:YES];
// 水平鏡像吃衅,YES->沿著X軸旋轉(zhuǎn)180°往踢,NO->還原
BOOL isHorizontalMirror = !self.imageresizerView.horizontalMirror;
[self.imageresizerView setHorizontalMirror:isHorizontalMirror animated:YES];
旋轉(zhuǎn)
// 1.順/逆時(shí)針旋轉(zhuǎn)90°(默認(rèn)逆時(shí)針)
[self.imageresizerView rotation];
// 若需要順時(shí)針旋轉(zhuǎn)可設(shè)置isClockwiseRotation屬性為YES
self.imageresizerView.isClockwiseRotation = YES;
// 2.自定義旋轉(zhuǎn)至目標(biāo)方向(支持4個(gè)方向,分別是垂直向上徘层、水平向左峻呕、垂直向下、水平向右)
[self.imageresizerView rotationToDirection:JPImageresizerVerticalDownDirection];
重置
重置目標(biāo)狀態(tài)趣效,方向垂直向上瘦癌,可重置為不同的resizeWHScale、圓切跷敬、蒙版
1. 一切按當(dāng)前狀態(tài)重置
- (void)recovery;
2. 以resizeWHScale重置(會(huì)移除圓切讯私、蒙版)
// 2.1 按初始裁剪寬高比(initialResizeWHScale)進(jìn)行重置
- (void)recoveryByInitialResizeWHScale;
- (void)recoveryByInitialResizeWHScale:(BOOL)isToBeArbitrarily;
// 2.2 按當(dāng)前裁剪寬高比進(jìn)行重置(如果resizeWHScale為0,則重置到整個(gè)裁剪元素區(qū)域)
- (void)recoveryByCurrentResizeWHScale;
- (void)recoveryByCurrentResizeWHScale:(BOOL)isToBeArbitrarily;
// 2.3 按目標(biāo)裁剪寬高比進(jìn)行重置(如果resizeWHScale為0,則重置到整個(gè)裁剪元素區(qū)域)
// targetResizeWHScale:目標(biāo)裁剪寬高比
// isToBeArbitrarily:重置之后 resizeWHScale 是否為任意比例(若為YES斤寇,最后 resizeWHScale = 0)
- (void)recoveryToTargetResizeWHScale:(CGFloat)targetResizeWHScale isToBeArbitrarily:(BOOL)isToBeArbitrarily;
3. 以圓切重置
- (void)recoveryToRoundResize;
- (void)recoveryToRoundResize:(BOOL)isToBeArbitrarily;
4. 以蒙版圖片重置
// 4.1 按當(dāng)前蒙版圖片重置
- (void)recoveryByCurrentMaskImage;
- (void)recoveryByCurrentMaskImage:(BOOL)isToBeArbitrarily;
// 4.2 指定蒙版圖片重置
- (void)recoveryToMaskImage:(UIImage *)maskImage isToBeArbitrarily:(BOOL)isToBeArbitrarily;
預(yù)覽
// 預(yù)覽模式:隱藏邊框桶癣,停止拖拽操作,用于預(yù)覽裁剪后的區(qū)域
// 1.默認(rèn)自帶動(dòng)畫(huà)效果
self.imageresizerView.isPreview = YES;
// 2.自定義是否帶動(dòng)畫(huà)效果
[self.imageresizerView setIsPreview:YES animated:NO]
保存當(dāng)前裁剪狀態(tài)
// 1.很Easy娘锁,直接調(diào)用saveCurrentConfigure方法獲取當(dāng)前裁剪的狀態(tài)牙寞,可用一個(gè)全局變量來(lái)保存該對(duì)象
JPImageresizerConfigure *savedConfigure = [self.imageresizerView saveCurrentConfigure];
// 2.重新打開(kāi)裁剪歷史
JPImageresizerView *imageresizerView = [JPImageresizerView imageresizerViewWithConfigure:savedConfigure imageresizerIsCanRecovery:^(BOOL isCanRecovery) {
......
} imageresizerIsPrepareToScale:^(BOOL isPrepareToScale) {
......
}];
[self.view addSubview:imageresizerView];
self.imageresizerView = imageresizerView;
// 3.可以設(shè)置JPImageresizerConfigure的isCleanHistoryAfterInitial屬性為YES,當(dāng)初始化結(jié)束后自動(dòng)清空歷史(默認(rèn)為YES)
// 或者直接調(diào)用cleanHistory方法清空歷史
- PS1:若保存的
savedConfigure.history.viewFrame
跟當(dāng)前的viewFrame
不一致莫秆,界面會(huì)導(dǎo)致錯(cuò)亂间雀,需要自行判斷是否一致才可重新打開(kāi); - PS2:另外目前只能在A(yíng)pp使用期間進(jìn)行保存镊屎,暫未實(shí)現(xiàn)持久化緩存惹挟。
其他
// 鎖定裁剪區(qū)域,鎖定后無(wú)法拖動(dòng)裁剪區(qū)域缝驳,NO則解鎖
self.imageresizerView.isLockResizeFrame = YES;
// 旋轉(zhuǎn)至水平方向時(shí)是否自適應(yīng)裁剪區(qū)域大小
// 當(dāng)圖片寬度比圖片高度小時(shí)匪煌,該屬性默認(rèn)YES,可手動(dòng)設(shè)為NO
self.imageresizerView.isAutoScale = NO;
安裝
JPImageresizerView 可通過(guò)CocoaPods安裝党巾,只需添加下面一行到你的podfile:
pod 'JPImageresizerView'
反饋地址
郵箱:zhoujianping24@hotmail.com
扣扣:184669029