Giter Club home page Giter Club logo

jpimageresizerview's Introduction

JPImageresizerView

Version License Platform Language

英文文档(English document) | 掘金 | 高仿小红书App可拖拽任意角度的裁剪功能

简介(当前版本:1.11.2)

一个专门裁剪图片、GIF、视频的轮子,简单易用,功能丰富(高自由度的参数设定、支持旋转和镜像翻转、蒙版、压缩等),能满足绝大部分裁剪的需求。

effect

Feature:
    ✅ 能自适应裁剪区域的缩放;
    ✅ 高自由度的参数设定,包括裁剪区域的间距、裁剪宽高比、是否自适应缩放等;
    ✅ 支持最多8个拖拽方向的裁剪区域;
    ✅ 支持上左下右的旋转;
    ✅ 水平和垂直的镜像翻转;
    ✅ 两种边框样式;
    ✅ 支持圆框裁剪;
    ✅ 自定义毛玻璃样式、边框颜色、背景颜色、遮罩透明度;
    ✅ 自定义边框图片;
    ✅ 可动态修改视图区域和裁剪区域间距,支持横竖屏切换;
    ✅ 可自定义蒙版图片裁剪;
    ✅ 可裁剪本地视频整段画面或某一帧画面;
    ✅ 可截取某一段本地视频,裁剪后并转成GIF;
    ✅ 可裁剪GIF;
    ✅ 可设置GIF的背景色、圆角、边框、轮廓描边、内容边距;
    ✅ 可保存当前裁剪状态;
    ✅ 图片支持N宫格裁剪;
    ✅ 兼容Swift&SwiftUI环境(参考Demo)。

TODO:
    🔘 Swift版本;
    🔘 固定不缩放裁剪区域;
    🔘 视频不再需要修正方向再裁剪;
    🔘 裁剪远程视频;
    🔘 持久化缓存裁剪历史;
    🔘 将视频裁剪部分(AVFoundation模块)分离出来;
    🔘 实现苹果相册裁剪功能中的自由拖拽旋转、翻转角度的效果。
    
注意:由于autoLayout不利于手势控制,所以目前使用的是frame布局,暂不支持autoLayout。

最新改动

1.可设置GIF的背景色、圆角、边框、轮廓描边、内容边距;
2.可使用本地图片组装GIF;
3.可获取图片目标像素的颜色值。

  • 可设置GIF的背景色、圆角、边框、轮廓描边、内容边距。

如何使用

初始化

1. 配置初始参数

可设置的裁剪元素(图片、GIF、视频),只能选择其中一个,并且不能为nil:
    - image:裁剪的图片/GIF(以UIImage传入)
    - imageData:裁剪的图片/GIF(以NSData传入)
    - videoURL:裁剪的本地视频(以NSURL传入)
    - videoAsset:裁剪的本地视频(以AVURLAsset传入)
    
其他部分可配置参数(更多可查看JPImageresizerView的头文件):
    - blurEffect:毛玻璃样式
    - borderImage:边框图片
    - frameType & strokeColor:边框样式&颜色
    - bgColor:背景色
    - maskAlpha:遮罩透明度
    - resizeWHScale:裁剪的宽高比
    - contentInsets:裁剪区域与视图的间距
    - maskImage:蒙版图片
    - gifSettings:GIF图像处理设置

图片/GIF

//【裁剪的图片/GIF】以UIImage传入
JPImageresizerConfigure *configure = [JPImageresizerConfigure defaultConfigureWithImage:image make:^(JPImageresizerConfigure *configure) {
    // 到这里已经有了默认参数值,可以在这里另外设置你想要的参数值(使用了链式编程方式)
    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);
}];

// 如果想要初始化为正方形,可设置 JPImageresizerConfigure 的 resizeWHScale 属性
configure.resizeWHScale = 1; // 默认为0,完全显示
// 另外如果还需要固定比例的话:
configure.isArbitrarily = YES; // 默认为YES

// 2.【裁剪的图片/GIF】以NSData传入
JPImageresizerConfigure *configure = [JPImageresizerConfigure defaultConfigureWithImageData:imageData make:^(JPImageresizerConfigure *configure) { ...... };

视频

关于从系统相册获取的视频,视频方向有可能是修改过的(即相册中旋转、翻转过),修改后的videoTrack.preferredTransform != CGAffineTransformIdentity,图片也会,不过好歹图片有个imageOrientation属性告知具体改动了什么,由于我才疏学浅,单单从preferredTransform并不知道是经过了具体的哪些改动,如果只是旋转还好,旋转+翻转后的数值都是不一定的,这样导致最后裁剪时会错乱,目前只好先修正方向后再进行裁剪,日后改进,希望能有缘之士给予指点!

初始化后再修正(先进入页面后再修正),具体操作可参照Demo:

// 1.【视频】以NSURL传入
JPImageresizerConfigure *configure = [JPImageresizerConfigure defaultConfigureWithVideoURL:videoURL make:^(JPImageresizerConfigure *configure) { ...... } fixErrorBlock:^(NSURL *cacheURL, JPImageresizerErrorReason reason) {
    // 初始化修正视频方向的错误回调
} fixStartBlock:^{
    // 初始化修正视频方向的开始回调
} fixProgressBlock:^(float progress) {
    // 初始化修正视频方向的进度回调 
} fixCompleteBlock:^(NSURL *cacheURL) {
    // 初始化修正视频方向的完成回调
}];

// 2.【视频】以AVURLAsset传入
[JPImageresizerConfigure defaultConfigureWithVideoAsset:videoAsset 
                                                   make:^(JPImageresizerConfigure *configure) { ...... } 
                                          fixErrorBlock:^(NSURL *cacheURL, JPImageresizerErrorReason reason) { ...... } 
                                          fixStartBlock:^{ ...... } fixProgressBlock:^(float progress) { ...... } 
                                       fixCompleteBlock:^(NSURL *cacheURL) { ...... }];

又或者先修正再初始化(先修正后再进入页面),可以使用JPImageresizerTool的API来修正,具体操作可参照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)) {
    // 无需修正,进入裁剪界面
    JPImageresizerConfigure *configure = [JPImageresizerConfigure defaultConfigureWithVideoAsset:videoAsset make:nil fixErrorBlock:nil fixStartBlock:nil fixProgressBlock:nil fixCompleteBlock:nil];
    ......
    return;
}

// 修正方向
[JPImageresizerTool fixOrientationVideoWithAsset:videoAsset fixErrorBlock:^(NSURL *cacheURL, JPImageresizerErrorReason reason) {
    // 修正视频方向的错误回调
} fixStartBlock:^(AVAssetExportSession *exportSession) {
    // 修正视频方向的开始回调
    // 返回exportSession,可监听进度或取消导出
} fixCompleteBlock:^(NSURL *cacheURL) {
    // 修正视频方向的完成回调
    // cacheURL:修正方向后的视频导出后的最终存放路径,默认该路径为NSTemporaryDirectory文件夹下,保存该路径,裁剪后删除视频。
    
    // 开始裁剪,进入裁剪界面
    JPImageresizerConfigure *configure = [JPImageresizerConfigure defaultConfigureWithVideoAsset:[AVURLAsset assetWithURL:cacheURL] make:nil fixErrorBlock:nil fixStartBlock:nil fixProgressBlock:nil fixCompleteBlock:nil];
    ......
}];
  • PS1:如果视频不需要修正,fixStartBlockfixProgressBlockfixErrorBlock均不会调用,会直接调用fixCompleteBlock,返回原路径;
  • PS2:如果确定是无需修正方向的视频,fixErrorBlockfixStartBlockfixProgressBlockfixCompleteBlocknil
  • PS3:更换视频:-setVideoURL: animated: fixErrorBlock: fixStartBlock: fixProgressBlock: fixCompleteBlock:-setVideoAsset: animated: fixErrorBlock: fixStartBlock: fixProgressBlock: fixCompleteBlock: 方法也与之同理,内部会判定是否需要修正;
  • PS4:如果需要初始化就固定裁剪宽高比(如圆切、蒙版等),需要设置JPImageresizerConfigureisArbitrarily属性为NO(默认为YES):
JPImageresizerConfigure *configure = [JPImageresizerConfigure darkBlurMaskTypeConfigureWithImage:nil make:^(JPImageresizerConfigure *configure) {
    configure
    .jp_maskImage([UIImage imageNamed:@"love.png"])
    .jp_isArbitrarily(NO);
}];

2. 创建JPImageresizerView对象并添加到视图上

JPImageresizerView *imageresizerView = [JPImageresizerView imageresizerViewWithConfigure:configure imageresizerIsCanRecovery:^(BOOL isCanRecovery) {
    // 可在这里监听到是否可以重置
    // 如果不需要重置(isCanRecovery为NO),可在这里做相应处理,例如将重置按钮设置为不可点或隐藏
    // PS:isCanRecovery仅针对[旋转]、[缩放]、[镜像]的变化情况,其他如裁剪宽高比、圆切等变化情况需用户自行判定能否重置
    // 具体操作可参照Demo
    // 注意循环引用
} imageresizerIsPrepareToScale:^(BOOL isPrepareToScale) {
    // 可在这里监听到裁剪区域是否预备缩放至适合范围
    // 如果预备缩放(isPrepareToScale为YES),此时裁剪、旋转、镜像功能不可用,可在这里做相应处理,例如将对应按钮设置为不可点或隐藏
    // 具体操作可参照Demo
    // 注意循环引用
}];
[self.view addSubview:imageresizerView];
self.imageresizerView = imageresizerView;

// 创建后均可动态修改configure的参数
self.imageresizerView.image = [UIImage imageNamed:@"Kobe.jpg"]; // 更换裁剪图片(默认带动画效果)
self.imageresizerView.resizeWHScale = 16.0 / 9.0; // 修改裁剪宽高比
self.imageresizerView.initialResizeWHScale = 0.0; // 默认为初始化时的resizeWHScale,调用 -recoveryByInitialResizeWHScale 方法进行重置则 resizeWHScale 会重置为该属性的值

// 注意:iOS11以下的系统,所在的controller最好设置automaticallyAdjustsScrollViewInsets为NO
// 不然imageresizerView会随导航栏或状态栏的变化产生偏移
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.创建imageresizerView
let imageresizerView = JPImageresizerView(configure: configure) { [weak self] isCanRecovery in
    // 当不需要重置设置按钮不可点
    self?.recoveryBtn.isEnabled = isCanRecovery
} imageresizerIsPrepareToScale: { [weak self] isPrepareToScale in
    // 当预备缩放设置按钮不可点,结束后可点击
    self?.operationView.isUserInteractionEnabled = !isPrepareToScale
}

// 3.添加到视图上
view.insertSubview(imageresizerView, at: 0)
self.imageresizerView = imageresizerView

具体使用可以参考Demo(JPCropViewController)。

裁剪

裁剪说明:
    1.裁剪过程是在子线程中执行,进度、错误、完成的回调都会切回主线程执行,如果是高清图片,裁剪前可添加HUD提示;
    2.compressScale:图片和GIF的压缩比例,大于等于1按原图尺寸裁剪,小于等于0则返回nil(例:compressScale = 0.5,1000 x 500 --> 500 x 250);
    3.cacheURL:缓存路径,可设置为nil,图片和GIF则不缓存,而视频会默认缓存到系统的NSTemporaryDirectory文件夹下,视频名为当前时间戳,格式为mp4;
    4.错误原因 JPImageresizerErrorReason 说明:
        - JPIEReason_NilObject:裁剪元素为空
        - JPIEReason_CacheURLAlreadyExists:缓存路径已存在其他文件
        - JPIEReason_NoSupportedFileType:不支持的文件类型
        - JPIEReason_VideoAlreadyDamage:视频文件已损坏
        - JPIEReason_VideoExportFailed:视频导出失败
        - JPIEReason_VideoExportCancelled:视频导出取消
    5.注意:缓存路径的图片格式会自动修正,例如原本写的是`xxx/xxx.jpeg`,由于使用了蒙版,裁剪后则会修正为`xxx/xxx.png`了,最终的缓存路径要以裁剪回调`completeBlock`中的`result.cacheURL`为准。

裁剪图片

// 1.以原图尺寸进行裁剪
[self.imageresizerView cropPictureWithCacheURL:cacheURL errorBlock:^(NSURL *cacheURL, JPImageresizerErrorReason reason) {
    // 错误的回调
    // reason:错误原因
    // 注意循环引用
} completeBlock:^(JPImageresizerResult *result) {
    // 裁剪完成
    // result:裁剪后的结果(JPImageresizerResult)
    // result.image:裁剪后的图片(已解码好的)
    // result.cacheURL:目标存放路径
    // result.isCacheSuccess:是否缓存成功(缓存不成功则cacheURL为nil)
    // 注意循环引用
}];


// 2.自定义压缩比例裁剪图片
// compressScale --- 压缩比例,大于等于1按原图尺寸裁剪,小于等于0则返回nil(例:compressScale = 0.5,1000 x 500 --> 500 x 250)
// completeBlock --- 裁剪完成的回调(返回裁剪后的结果,包含已解码好的图片、缓存路径)
- (void)cropPictureWithCompressScale:(CGFloat)compressScale
                            cacheURL:(NSURL *)cacheURL
                          errorBlock:(JPImageresizerErrorBlock)errorBlock
                       completeBlock:(JPCropDoneBlock)completeBlock;
  • 裁剪N宫格图片

// 1.自定义N宫格裁剪
// columnCount:N宫格的列数(最小1列)
// rowCount:N宫格的行数(最小1行)
// compressScale --- 压缩比例,大于等于1按原图尺寸裁剪,小于等于0则返回nil(例:compressScale = 0.5,1000 x 500 --> 500 x 250)
// bgColor --- N宫格的背景色(如果图片有透明区域,或者设置了蒙版的情况才生效,设置隐藏(透明)区域的背景色)
[self.imageresizerView cropGirdPicturesWithColumnCount:4 rowCount:2 compressScale:1 bgColor:UIColor.redColor cacheURL:cacheURL errorBlock:^(NSURL *cacheURL, JPImageresizerErrorReason reason) {
    // 错误的回调
    // reason:错误原因
    // 注意循环引用
} completeBlock:^(JPImageresizerResult *originResult, NSArray<JPImageresizerResult *> *fragmentResults, NSInteger columnCount, NSInteger rowCount) {
    // 裁剪完成
    // originResult:裁剪后的原图结果(开始N宫格之前)
    // fragmentResults:裁剪后的原图被裁剪成N宫格图片的结果集合(共 columnCount * rowCount 个)
    // columnCount:调用该方法时传入的列数
    // rowCount:调用该方法时传入的行数
    // 注意循环引用
}];

// 2.九宫格裁剪(3行3列)
- (void)cropNineGirdPicturesWithCompressScale:(CGFloat)compressScale
                                      bgColor:(UIColor *)bgColor
                                     cacheURL:(NSURL *)cacheURL
                                   errorBlock:(JPImageresizerErrorBlock)errorBlock
                                completeBlock:(JPCropNGirdDoneBlock)completeBlock;

裁剪GIF

// 1.原图尺寸裁剪GIF
[self.imageresizerView cropGIFWithCacheURL:cacheURL errorBlock:^(NSURL *cacheURL, JPImageresizerErrorReason reason) {
    // 错误的回调
    // reason:错误原因
    // 注意循环引用
} completeBlock:^(JPImageresizerResult *result) {
    // 裁剪完成
    // result:裁剪后的结果(JPImageresizerResult)
    // result.image:裁剪后的GIF(已解码好的)
    // result.cacheURL:目标存放路径
    // result.isCacheSuccess:是否缓存成功(缓存不成功则cacheURL为nil)
    // 注意循环引用
}];

// 2.自定义压缩比例裁剪GIF
// completeBlock --- 裁剪完成的回调(返回裁剪后的结果,包含已解码好的GIF、缓存路径)
- (void)cropGIFWithCompressScale:(CGFloat)compressScale
                        cacheURL:(NSURL *)cacheURL
                      errorBlock:(JPImageresizerErrorBlock)errorBlock
                   completeBlock:(JPCropDoneBlock)completeBlock;

// 3.自定义裁剪GIF
// isReverseOrder --- 是否倒放
// rate --- 速率
// completeBlock --- 裁剪完成的回调(返回裁剪后的结果,包含已解码好的GIF、缓存路径)
- (void)cropGIFWithCompressScale:(CGFloat)compressScale
                  isReverseOrder:(BOOL)isReverseOrder
                            rate:(float)rate
                        cacheURL:(NSURL *)cacheURL
                      errorBlock:(JPImageresizerErrorBlock)errorBlock
                   completeBlock:(JPCropDoneBlock)completeBlock;
  • 对GIF的图像进行处理

原GIF:

// 1.配置需处理的设置
JPImageProcessingSettings *settings = [[JPImageProcessingSettings alloc] init];
settings.backgroundColor = UIColor.blackColor; // 背景色
settings.outlineStrokeColor = UIColor.whiteColor; // 轮廓描边颜色
settings.outlineStrokeWidth = 3; // 轮廓描边大小
settings.cornerRadius = 30; // 圆角

// 2.在裁剪前设置即可`gifSettings`(可动态设置)
self.imageresizerView.gifSettings = settings;

处理后的GIF:

  • 裁剪GIF的其中一帧
// 1.原图尺寸裁剪GIF当前帧画面
// completeBlock --- 裁剪完成的回调(返回裁剪后的结果,包含已解码好的图片、缓存路径)
- (void)cropGIFCurrentIndexWithCacheURL:(NSURL *)cacheURL
                             errorBlock:(JPImageresizerErrorBlock)errorBlock
                          completeBlock:(JPCropDoneBlock)completeBlock;

// 2.自定义压缩比例裁剪GIF当前帧画面
// completeBlock --- 裁剪完成的回调(返回裁剪后的结果,包含已解码好的图片、缓存路径)
- (void)cropGIFCurrentIndexWithCompressScale:(CGFloat)compressScale
                                    cacheURL:(NSURL *)cacheURL
                                  errorBlock:(JPImageresizerErrorBlock)errorBlock
                               completeBlock:(JPCropDoneBlock)completeBlock;

// 3.自定义压缩比例裁剪GIF指定帧画面
// index --- 第几帧画面
// 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:可以设置isLoopPlaybackGIF自主选择裁剪哪一帧(默认为NO,设置为YES会自动播放GIF)

self.imageresizerView.isLoopPlaybackGIF = NO;

裁剪本地视频

PS:目前只针对本地视频,远程视频暂未适配。

// 裁剪整段视频
// cacheURL:如果为nil,会默认缓存到系统的NSTemporaryDirectory文件夹下,视频名为当前时间戳,格式为mp4
[self.imageresizerView cropVideoWithCacheURL:cacheURL errorBlock:^(NSURL *cacheURL, JPImageresizerErrorReason reason) {
    // 错误的回调
    // reason:错误原因
    // 注意循环引用
} progressBlock:^(float progress) {
    // 监听进度
    // progress:0~1
    // 注意循环引用
} completeBlock:^(JPImageresizerResult *result) {
    // 裁剪完成
    // result:裁剪后的结果(JPImageresizerResult)
    // result.cacheURL:目标存放路径,如果为nil,会默认缓存到系统的NSTemporaryDirectory文件夹下,视频名为当前时间戳,格式为mp4
    // result.isCacheSuccess:是否缓存成功(缓存不成功则cacheURL为nil)
    // 注意循环引用
}];

// 可设置视频导出质量
// presetName --- 系统的视频导出质量,如:AVAssetExportPresetLowQuality,AVAssetExportPresetMediumQuality,AVAssetExportPresetHighestQuality等
- (void)cropVideoWithPresetName:(NSString *)presetName
                       cacheURL:(NSURL *)cacheURL
                     errorBlock:(JPImageresizerErrorBlock)errorBlock
                  progressBlock:(JPExportVideoProgressBlock)progressBlock
                  completeBlock:(JPCropDoneBlock)completeBlock;

// 取消视频导出
// 当视频正在导出时调用即可取消导出,触发errorBlock回调(JPIEReason_ExportCancelled)
- (void)videoCancelExport;

PS:由于视频的宽高都必须是16的整数倍,否则导出后系统会自动对尺寸进行校正,不足的地方会以绿边的形式进行填充,因此我在方法内部对裁剪尺寸做了对16除余的修改,最后导出视频的宽高比有可能跟指定的宽高比有些许差异。

  • 裁剪视频的其中一帧
// 1.原图尺寸裁剪视频当前帧画面
// cacheURL --- 缓存路径(可设置为nil,则不会缓存)
// completeBlock --- 裁剪完成的回调(返回裁剪后的结果,包含已解码好的图片、缓存路径)
- (void)cropVideoCurrentFrameWithCacheURL:(NSURL *)cacheURL
                               errorBlock:(JPImageresizerErrorBlock)errorBlock
                            completeBlock:(JPCropDoneBlock)completeBlock;

// 2.自定义压缩比例裁剪视频当前帧画面
// cacheURL --- 缓存路径(可设置为nil,则不会缓存)
// completeBlock --- 裁剪完成的回调(返回裁剪后的结果,包含已解码好的图片、缓存路径)
- (void)cropVideoCurrentFrameWithCompressScale:(CGFloat)compressScale
                                      cacheURL:(NSURL *)cacheURL
                                    errorBlock:(JPImageresizerErrorBlock)errorBlock
                                 completeBlock:(JPCropDoneBlock)completeBlock;

// 3.自定义压缩比例裁剪视频指定帧画面
// second --- 第几秒画面
// cacheURL --- 缓存路径(可设置为nil,则不会缓存)
// completeBlock --- 裁剪完成的回调(返回裁剪后的结果,包含已解码好的图片、缓存路径)
- (void)cropVideoOneFrameWithSecond:(float)second
                      compressScale:(CGFloat)compressScale
                           cacheURL:(NSURL *)cacheURL
                         errorBlock:(JPImageresizerErrorBlock)errorBlock
                      completeBlock:(JPCropDoneBlock)completeBlock;
  • 截取视频某一段裁剪后转GIF
// 1.视频从当前时间开始截取指定秒数画面转GIF(fps = 10,rate = 1,maximumSize = 500 * 500)
// duration --- 截取多少秒
// completeBlock --- 裁剪完成的回调(返回裁剪后的结果,包含已解码好的GIF、缓存路径)
- (void)cropVideoToGIFFromCurrentSecondWithDuration:(NSTimeInterval)duration
                                           cacheURL:(NSURL *)cacheURL
                                         errorBlock:(JPImageresizerErrorBlock)errorBlock
                                      completeBlock:(JPCropDoneBlock)completeBlock;

// 2.视频自定义截取指定秒数画面转GIF
// duration --- 截取多少秒
// fps --- 帧率(设置为0则以视频真身帧率)
// rate --- 速率
// maximumSize --- 截取的尺寸(设置为0则以视频真身尺寸)
// completeBlock --- 裁剪完成的回调(返回裁剪后的结果,包含已解码好的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:裁剪整段视频画面圆切、蒙版的功能不能使用,目前只对图片和GIF有效。

蒙版

mask

// 设置蒙版图片(目前仅支持png图片)
self.imageresizerView.maskImage = [UIImage imageNamed:@"love.png"];

// 直接设置该值即是调用 -setMaskImage: isToBeArbitrarily: animated: 方法,其中默认 isToBeArbitrarily = (maskImage ? NO : self.isArbitrarily),isAnimated = YES

// 移除蒙版图片
self.imageresizerView.maskImage = nil;

maskdone

  • PS:如果使用了蒙版图片,那么最后裁剪出来的是png图片,因此裁剪后体积有可能会比原本的图片更大。

圆切

round_resize

// 设置圆切
// 设置后,resizeWHScale为1:1,半径为宽高的一半,边框的上、左、下、右的中部均可拖动。
self.imageresizerView.isRoundResize = YES;

// 直接设置该值即是调用 -setIsRoundResize: isToBeArbitrarily: animated: 方法,其中默认 isToBeArbitrarily = (isRoundResize ? NO : self.isArbitrarily),isAnimated = YES

// 还原矩形
self.imageresizerView.isRoundResize = NO;
// 或者只需设置一下resizeWHScale为任意值即可
self.imageresizerView.resizeWHScale = 0.0;

横竖屏切换

screenswitching

// 需要用户去监听横竖屏的切换,或自己手动切换时,调用该方法刷新
// 1.updateFrame:刷新的Frame(例如横竖屏切换,传入self.view.bounds即可)
// 2.contentInsets:裁剪区域与主视图的内边距
// 3.duration:刷新时长(大于0即带有动画效果)
//【具体操作可参照Demo】
[self.imageresizerView updateFrame:self.view.bounds contentInsets:contentInsets duration:duration];

更改边框样式

concise classic

// 目前只提供两种边框样式,分别是简洁样式JPConciseFrameType,和经典样式JPClassicFrameType
// 可在初始化或直接设置frameType属性来修改边框样式
self.imageresizerView.frameType = JPClassicFrameType;

自定义边框图片

stretch_mode tile_mode

// 使用自定义边框图片(例:平铺模式)
UIImage *tileBorderImage = [[UIImage imageNamed:@"dotted_line"] resizableImageWithCapInsets:UIEdgeInsetsMake(14, 14, 14, 14) resizingMode:UIImageResizingModeTile];

// 设置边框图片与边线的偏移量(即CGRectInset,用于调整边框图片与边线的差距)
self.imageresizerView.borderImageRectInset = CGPointMake(-1.75, -1.75);

// 设置边框图片(若为nil则使用frameType的边框)
self.imageresizerView.borderImage = tileBorderImage;

切换裁剪宽高比

  • PS:设置裁剪宽高比会自动移除圆切和蒙版
// 1.自定义参数切换
/**
 * resizeWHScale:    目标裁剪宽高比(0则为任意比例)
 * isToBeArbitrarily:切换之后 resizeWHScale 是否为任意比例(若为YES,最后 resizeWHScale = 0)
 * animated:         是否带动画效果
 */
[self.imageresizerView setResizeWHScale:(16.0 / 9.0) isToBeArbitrarily:YES animated:YES];

// 2.直接切换
self.imageresizerView.resizeWHScale = 1.0;
// 默认切换之后保存最新的 resizeWHScale,且自带动画效果,如果设置为0,以当前裁剪框的宽高比设置,并且最后 isArbitrarily = YES,相当于:
[self.imageresizerView setResizeWHScale:1.0 isToBeArbitrarily:(resizeWHScale <= 0) animated:YES];

// 是否可以任意比例拖拽(包括圆切、蒙版)
self.imageresizerView.isArbitrarily = !self.imageresizerView.isArbitrarily;

// 更多API可查看 JPImageresizerView.h 上的注释

自定义毛玻璃样式、边框颜色、背景颜色、遮罩透明度

// 设置毛玻璃样式(默认带动画效果)
self.imageresizerView.blurEffect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleDark];

// 设置边框颜色(默认带动画效果)
self.imageresizerView.strokeColor = UIColor.whiteColor;

// 设置背景颜色(默认带动画效果)
self.imageresizerView.bgColor = UIColor.blackColor;

// 设置遮罩透明度(默认带动画效果)
// PS:跟毛玻璃互斥,当设置了毛玻璃则遮罩为透明
self.imageresizerView.maskAlpha = 0.5; // blurEffect = nil 才生效

// 一步设置毛玻璃样式、边框颜色、背景颜色、遮罩透明度
[self.imageresizerView setupStrokeColor:strokeColor blurEffect:[UIBlurEffect effectWithStyle:UIBlurEffectStyleDark] bgColor:UIColor.blackColor maskAlpha: 0.5 animated:YES];

镜像翻转

mirror

// 1.垂直镜像,YES->沿着Y轴旋转180°,NO->还原
BOOL isVerticalityMirror = !self.imageresizerView.verticalityMirror;
self.imageresizerView.verticalityMirror = isVerticalityMirror;
// 默认自带动画效果,相当于:
[self.imageresizerView setVerticalityMirror:isVerticalityMirror animated:YES];

// 2.水平镜像,YES->沿着X轴旋转180°,NO->还原
BOOL isHorizontalMirror = !self.imageresizerView.horizontalMirror;
self.imageresizerView.horizontalMirror = isHorizontalMirror;
// 默认自带动画效果,相当于:
[self.imageresizerView setHorizontalMirror:isHorizontalMirror animated:YES];

旋转

// 1.顺/逆时针旋转90°(默认逆时针)
[self.imageresizerView rotation];

// 若需要顺时针旋转可设置isClockwiseRotation属性为YES
self.imageresizerView.isClockwiseRotation = YES;

// 2.自定义旋转至目标方向(支持4个方向,分别是垂直向上、水平向左、垂直向下、水平向右)
[self.imageresizerView rotationToDirection:JPImageresizerVerticalDownDirection];

重置

重置目标状态,方向垂直向上,可重置为不同的resizeWHScale、圆切、蒙版

1. 一切按当前状态重置

- (void)recovery;

2. 以resizeWHScale重置(会移除圆切、蒙版)

// 2.1 按初始裁剪宽高比(initialResizeWHScale)进行重置
- (void)recoveryByInitialResizeWHScale;
- (void)recoveryByInitialResizeWHScale:(BOOL)isToBeArbitrarily;

// 2.2 按当前裁剪宽高比进行重置(如果resizeWHScale为0,则重置到整个裁剪元素区域)
- (void)recoveryByCurrentResizeWHScale;
- (void)recoveryByCurrentResizeWHScale:(BOOL)isToBeArbitrarily;

// 2.3 按目标裁剪宽高比进行重置(如果resizeWHScale为0,则重置到整个裁剪元素区域)
// targetResizeWHScale:目标裁剪宽高比
// isToBeArbitrarily:重置之后 resizeWHScale 是否为任意比例(若为YES,最后 resizeWHScale = 0)
- (void)recoveryToTargetResizeWHScale:(CGFloat)targetResizeWHScale isToBeArbitrarily:(BOOL)isToBeArbitrarily;

3. 以圆切重置

- (void)recoveryToRoundResize;
- (void)recoveryToRoundResize:(BOOL)isToBeArbitrarily;

4. 以蒙版图片重置

// 4.1 按当前蒙版图片重置
- (void)recoveryByCurrentMaskImage;
- (void)recoveryByCurrentMaskImage:(BOOL)isToBeArbitrarily;

// 4.2 指定蒙版图片重置
- (void)recoveryToMaskImage:(UIImage *)maskImage isToBeArbitrarily:(BOOL)isToBeArbitrarily;

预览

// 预览模式:隐藏边框,停止拖拽操作,用于预览裁剪后的区域

self.imageresizerView.isPreview = YES;

// 默认自带动画效果,相当于:
[self.imageresizerView setIsPreview:YES animated:YES];

保存当前裁剪状态

// 1.很Easy,直接调用saveCurrentConfigure方法获取当前裁剪的状态,可用一个全局变量来保存该对象
JPImageresizerConfigure *savedConfigure = [self.imageresizerView saveCurrentConfigure];

// 2.重新打开裁剪历史
JPImageresizerView *imageresizerView = [JPImageresizerView imageresizerViewWithConfigure:savedConfigure imageresizerIsCanRecovery:^(BOOL isCanRecovery) {
    ......
} imageresizerIsPrepareToScale:^(BOOL isPrepareToScale) {
    ......
}];
[self.view addSubview:imageresizerView];
self.imageresizerView = imageresizerView;

// 3.可以设置JPImageresizerConfigure的isCleanHistoryAfterInitial属性为YES,当初始化结束后自动清空历史(默认为YES)
// 或者直接调用cleanHistory方法清空历史

save

  • PS1:若保存的savedConfigure.history.viewFrame跟当前的viewFrame不一致,界面会导致错乱,需要自行判断是否一致才可重新打开;
  • PS2:另外目前只能在App使用期间进行保存,暂未实现持久化缓存。

其他

// 锁定裁剪区域,锁定后无法拖动裁剪区域,NO则解锁
self.imageresizerView.isLockResizeFrame = YES;

// 旋转至水平方向时是否自适应裁剪区域大小
// 当图片宽度比图片高度小时,该属性默认YES,可手动设为NO
self.imageresizerView.isAutoScale = NO;

各版本的主要更新

版本 更新内容
1.11.1~1.11.2 1. 添加隐私清单PrivacyInfo;
2. 修复裁剪gif后JPImageresizerResult对象的image属性为空的问题。
1.11.0 1. 可设置GIF的背景色、圆角、边框、轮廓描边、内容边距;
2. 可使用本地图片组装GIF;
3. 可获取图片目标像素的颜色值;
4. 修复引起内存泄漏的漏洞。
1.10.0~1.10.5 1. 修复旋转方向错误的问题;
2. 修复有透明背景的GIF裁剪后图像重叠的问题;
3. 修复仅修改裁剪宽高比而无法重置的问题;
4. 新增isCanRecovery只读属性:是否可重置,该属性仅针对旋转缩放镜像的变化情况,其他如裁剪宽高比圆切等变化情况需用户自行判定能否重置,与JPImageresizerIsCanRecoveryBlock中返回的isCanRecovery一致;
5. 添加一些防Crash逻辑。
1.9.0~1.9.9 1. 图片新增N宫格裁剪;
2. 所有的裁剪完成回调统一返回JPImageresizerResult实例;
3. 兼容Swift环境;
4. 修复isShowGridlinesWhenDragging属性为YES时,拖动图片本身没有显示网格的问题;
5. 修复部分音频有问题的视频裁剪出错的问题;
6. 修复裁剪视频或GIF时进度条没有显示的问题;
7. 新增更多Configure初始化和可自定义旋转至目标方向的API;
8. 修复在预览模式下会显示进度条的问题。
1.7.8~1.8.3 1. 新增可保存当前历史状态的功能;
2. 修复GIF裁剪某一帧画面时的后缀名误设问题;
3. 修复仅放大而无法裁剪的问题;
4. 修复从系统相册选择的视频没有画面的问题;
5. 修复预览模式下进度条没有隐藏的问题。
1.7.6~1.7.7 1. 修复了固定比例旋转时无故放大的问题;
2. 修复iOS14版本下自定义进度条的拖动块消失的问题。
1.7.3~1.7.5 1. 修复了初始化无法固定裁剪比例的问题;
2. 现在圆切和蒙版均可设置是否自由拖拽;
3. 优化了设置裁剪宽高比和重置的接口;
4. 优化了图片缓存逻辑;
5. 修复了GIF时长过短导致截取错误的问题。
1.7.1~1.7.2 1. 新增修正视频方向的功能(有待改进);
2. 裁剪视频可以以AVURLAsset形式传入;
3. 优化切换裁剪元素的过渡。
1.7.0 1. 新增可裁剪GIF功能,可以裁剪一整个GIF文件,也可以裁剪其中一帧画面,可设置是否倒放、速率;
2. 视频可以截取任意一段转成GIF,可设置帧率、尺寸;
3. 裁剪图片和GIF可以以UIImage形式传入,也可以以NSData形式传入;
4. 图片和GIF可设置缓存路径保存到本地磁盘;
5. 极大地优化了裁剪逻辑。
1.6.0~1.6.3 1. 可裁剪本地视频整段画面或某一帧画面,并且可以动态切换裁剪素材;
2. 现在默认经典模式下,闲置时网格线会隐藏,拖拽时才会显示,新增了isShowGridlinesWhenIdle属性,可以跟isShowGridlinesWhenDragging属性自定义显示时机;
3. 修复了设置蒙版图片后切换裁剪素材时的方向错乱问题;
4. 优化图片裁剪的逻辑,优化API。
1.5.0~1.5.3 1. 新增自定义蒙版图片功能,从而实现可自定义任意裁剪区域;
2. 修复了经旋转重置后裁剪宽高比错乱的问题;
3. 优化了旋转、翻转的过渡动画。
1.4.0 1. 新增isBlurWhenDragging属性:拖拽时是否遮罩裁剪区域以外的区域;
2. 新增isShowGridlinesWhenDragging属性:拖拽时是否能继续显示网格线(frameType 为 JPClassicFrameType 且 gridCount > 1 才显示网格);
3. 新增gridCount属性:每行/列的网格数(frameType 为 JPClassicFrameType 且 gridCount > 1 才显示网格)。
1.3.8~1.3.9 1. 适配横竖屏切换;
2. 废除verBaseMargin和horBaseMargin属性,统一使用contentInsets设置裁剪区域与视图的间距;
3. 优化代码,并减少裁剪误差。
1.2.1~1.3.6 1. 新增圆切样式;
2. 中间的点/块可隐藏;
3. 可动态切换图片、设置边框颜色和背景颜色,可设置是否带有动画效果;
4. 毛玻璃效果可设置系统现有的所有效果;
5. 适配深色/浅色模式的切换(前提是颜色使用的是系统的动态颜色);
6. 优化逻辑。
1.2.0 1. 固定比例的裁剪宽高比,裁剪边框也均可拖拽8个方向;
2. 优化了显示/隐藏毛玻璃效果。
1.1.2~1.1.5 1. 优化计算逻辑;
2. 初始化时可自定义最大缩放比例(maximumZoomScale)。
1.1.1 1. 新增 imageresizeWHScale 属性,获取当前裁剪框的宽高比;
2. 新增 isToBeArbitrarily 关键字,用于设置裁剪宽高比、重置之后 resizeWHScale 是否为任意比例(若为YES,最后 resizeWHScale = 0),即可以继续任意拖拽裁剪框,对设置裁剪宽高比、重置等方法进行了修改,详情请查看Demo;
3. 直接设置 resizeWHScale、verticalityMirror、horizontalMirror、isPreview 默认自带动画效果(isAnimated = YES,其中 resizeWHScale 的 isToBeArbitrarily = NO)。
1.1.0 1. 现在可以自定义边框图片,新增borderImage(边框图片)和borderImageRectInset(边框图片与边线的偏移量)接口用于设置自定义边框图片;
2. 优化计算逻辑。
1.0.1~1.0.4 1. recovery方法更名为recoveryByInitialResizeWHScale,意思按initialResizeWHScale进行重置,避免误导。
2. 裁剪后不再按参照宽度来进行压缩了,现在按比例来进行压缩(现在使用scale,referenceWidth已废除);
3. 优化了裁剪和压缩逻辑;
1.0.0 1. 新增了isPreview属性,用于预览裁剪后的区域;
2. 新增了initialResizeWHScale属性,初始裁剪宽高比,重置时resizeWHScale会重置为该属性的值;
3. 新增recoveryByCurrentResizeWHScale方法,重置时不改变resizeWHScale;
4. 新增recoveryByResizeWHScale:方法,重置时可修改成任意resizeWHScale;
5. 修复了不断切换resizeWHScale时不断缩放的问题;
6. 优化了切换resizeWHScale、手指拖动时的交互效果。
0.5.1~0.5.3 1. 修复了设置镜像后的旋转、裁剪错乱问题;
2. 修复了切换裁剪比例时的缩放错误问题;
3. 移除isRotatedAutoScale属性(该属性会导致多处错误,且不利于优化,所以决定移除);
4. 优化计算逻辑。
0.4.9 新增edgeLineIsEnabled属性:用于设置裁剪框边线能否进行对边拖拽,只有当裁剪宽高比(resizeWHScale)为0,即任意比例时才有效,适用于所有边框样式,默认为yes。(之前是只有触碰上下左右的中点才可以进行对边拖拽,现在是整条边线的作用范围)
0.4.3~0.4.6 1. 修复了image的scale不为1的情况下裁剪错误问题;
2. 移除裁剪方法(imageresizerWithComplete:isOriginImageSize:),新增(originImageresizerWithComplete:)来代替原图尺寸裁剪;
3. 新增两个压缩尺寸裁剪方法(imageresizerWithComplete:referenceWidth:)和(imageresizerWithComplete:),其中referenceWidth为裁剪的图片的参照宽度,例如设置为375,如果裁剪区域为图片宽度的一半,则裁剪的图片宽度为187.5,而高度则根据宽高比得出,最大和最小不超过原图和imageView两者的宽度。
4. 修复了原图裁剪导致的内存泄露;
5. 修复了长久以来旋转后没有自动调整至最大尺寸的问题;
6. 修复了拖拽边框松手时没有立刻更新拖拽区域的问题。
0.4.1 1. 优化了重置动画;
2. 裁剪方法(imageresizerWithComplete:isOriginImageSize:)新增 isOriginImageSize 参数,YES 为裁剪的图片尺寸按原图尺寸裁剪,NO 则为屏幕尺寸。
0.3.8~0.3.9 1. 修复1:1比例情况下旋转导致错位的问题;
2. 优化代码结构,更好的注释。
0.3.6 1. 修复了图片旋转和镜像后裁剪位置错乱的问题;
2. 新增边框样式:只有4角拖拽方向的简洁样式(JPConciseWithoutOtherDotFrameType)。
0.3.4 修复了指定裁剪宽高比(resizeWHScale大于0)的情况下,重置动画的错乱(recovery方法)。
0.3.3 新增resizeWHScale的动画形式的设置接口(-setResizeWHScale:animated:)。
说明:平时裁剪头像区域一般都是使用1:1的比例,但如果一进去就以该比例呈现,就会立马裁掉超出区域,可能会给人一种图片尺寸改变了的错觉,所以个人建议进去页面后(例如控制器的viewDidApper时)再调用改方法重新调整宽高比(请看gif图效果),这样用户体验会好点。
0.3.2 1. 新增【裁剪区域预备缩放至适应范围的回调】,当预备缩放时裁剪、旋转、镜像功能不可用,可在这回调中作相应处理;
2. 修改【旋转后是否自动缩放】的属性名 isAutoScale -> isRotatedAutoScale。
0.3.0 1. 修正旋转水平方向时自动整体自适应缩小的问题,现在为图片宽度比图片高度小时才自适应,也可以手动设定;
2. 新增锁定功能,裁剪区域可锁定,无法继续拖动;
3. 新增镜像功能,可进行垂直方向和水平方向镜像操作。
0.2.3 1. 修复相册照片方向错乱的bug;
2. 修复水平方向边框点和线有所缩小的问题;
3. 更正属性的注释。
0.2.0 1. 新增高斯模糊的遮罩样式;
2. 可设置动画曲线;
3. 可设置裁剪区域的内边距;
4. 新增JPImageresizerConfigure类,更加方便设定参数。

安装

JPImageresizerView 可通过CocoaPods安装,只需添加下面一行到你的podfile:

pod 'JPImageresizerView'

版本更新指令:pod update --no-repo-update

反馈地址

扣扣:184669029
E-mail: [email protected]
博客:https://juejin.im/user/5e55f27bf265da575c16c187

License

JPImageresizerView is available under the MIT license. See the LICENSE file for more info.

jpimageresizerview's People

Contributors

rogue24 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

jpimageresizerview's Issues

需求建议

大佬 能不能加个block实时返回裁剪框选中后的视频相对于原始视频尺寸裁剪的rect

编译失败

在子模块里引入了这个库,编译失败

1

不好意思还有一个问题,我还要做什么才能显示?

@interface EditImageViewController ()

{
JPImageresizerView *_imageresizerView;
}

@EnD

@implementation EditImageViewController

  • (void)viewDidLoad {
    [super viewDidLoad];
    // 注意:iOS11以下的系统,所在的controller最好设置automaticallyAdjustsScrollViewInsets为NO,不然就会随导航栏或状态栏的变化产生偏移
    if (@available(iOS 11.0, *)) {

    } else {
    self.automaticallyAdjustsScrollViewInsets = NO;
    }

    [self addSubviews];

}

  • (void)addSubviews {
    [self.view addSubview:_imageresizerView];
    }

  • (JPImageresizerConfigure *)configure {
    if (_configure == nil) {
    self.editImage = [UIImage imageNamed:@"Kobe.jpg"];
    _configure = [JPImageresizerConfigure defaultConfigureWithResizeImage:self.editImage
    make:^(JPImageresizerConfigure *configure) {
    configure
    .jp_maskAlpha(0.5)
    .jp_frameType(JPConciseFrameType)
    .jp_isClockwiseRotation(YES)
    .jp_animationCurve(JPAnimationCurveEaseOut)
    .jp_viewFrame([UIScreen mainScreen].bounds);
    }];
    }

    return _configure;
    }

  • (JPImageresizerView *)imageresizerView {
    if (_imageresizerView == nil) {
    kWEAK_SELF

      _imageresizerView = [JPImageresizerView imageresizerViewWithConfigure:self.configure
                                                  imageresizerIsCanRecovery:^(BOOL isCanRecovery) {
          
          
      }
                                               imageresizerIsPrepareToScale:^(BOOL isPrepareToScale) {
          
      }];
    

    }

    return _imageresizerView;
    }

裁剪问题

我们有个需求,要求裁剪的图片为2寸照片,像素为413*626,这个用咱的sdk的话需要怎么设置。求解答

裁剪图片崩溃

#0 Thread

CALayerInvalidGeometry

CALayer position contains NaN: [177 nan]. Layer: <CALayer:0x280837fe0; position = CGPoint (0 0); bounds = CGRect (0 0; 0 0); delegate = <UIImageView: 0x103c27720; frame = (0 0; 0 0); layer = <CALayer: 0x280837fe0>>; opaque = YES; allowsGroupOpacity = YES; >

0 CoreFoundation __CFBundleDlfcnGetSymbolByNameWithSearch + 136
1 libobjc.A.dylib objc_exception_throw + 60
2 CoreFoundation -[__NSCFCalendar dateByAddingComponents:toDate:options:] + 996
3 QuartzCore cons_CALayer_kCAValueRect(unsigned int, bool) + 12
4 QuartzCore cons_CALayer_kCAValuePoint(unsigned int, bool) + 156
5 QuartzCore cons_CALayer_kCAValueUnsignedInt(unsigned int, bool) + 64
6 UIKitCore -[_UIViewLayoutFeedbackLoopDebugger description] + 1576
7 UIKitCore -[UIKeyboardEmojiFamilyConfigurationView _updateReferencedKeySelectedVariantIndexBasedOnCurrentConfiguration] + 408
8 JPImageresizerView -[JPImageresizerView updateImageViewFrameWithImage:] + 320
9 JPImageresizerView -[JPImageresizerView setupImageViewWithImage:] + 176
10 JPImageresizerView -[JPImageresizerView initWithResizeImage:frame:frameType:animationCurve:blurEffect:bgColor:maskAlpha:strokeColor:verBaseMargin:horBaseMargin:resizeWHScale:contentInsets:borderImage:borderImageRectInset:maximumZoomScale:isRoundResize:isShowMidDots:imageresizerIsCanRecovery:imageresizerIsPrepareToScale:] + 928
11 JPImageresizerView +[JPImageresizerView imageresizerViewWithConfigure:imageresizerIsCanRecovery:imageresizerIsPrepareToScale:] + 612

好像是图片宽高没有拿到,导致的问题

裁剪比例来回切换会导致图片无限放大

- (void)updateImageOriginFrameWithDirection:(JPImageresizerRotationDirection)rotationDirection

这个方法里面获取的imageView的宽高(baseImageW、baseImageH)是不会变的,就会导致即使图片宽高已经超过裁剪框,图片也会自动放大。我觉得是不是需要乘以一下当前scrollView的zoomScale更合适一些?

如何自定义蒙版图片

1: 可以自定义蒙版图片么?
2: shapeList的工作原理;i是什么 有点没看懂代码 那些蒙版图片是怎么绘制出来的?

能否增加拍摄视频功能

当前是选择本地视频进行编辑,能否增加拍摄视频时,给出一个视频宽高比,进行视频拍摄。还有编辑视频长度,获取封面等功能,类似于微信视频号的功能。谢谢

部分属性设置无效

为啥有些属性在JPImageresizerConfigure的初始化block中设置无效,但是在JPImageresizerView的实例中设置就有效?

裁剪有留白的情况

在xsMax手机上进行裁剪横图的时候,出现裁剪后的图片有留白的情况。
目测代码:
// 获取裁剪区域
CGFloat imageScale = resultImage.scale;
CGFloat imageWidth = resultImage.size.width;
CGFloat imageHeight = resultImage.size.height;
CGFloat cropX = imageWidth * (cropFrame.origin.x / relativeSize.width);
CGFloat cropY = imageHeight * (cropFrame.origin.y / relativeSize.height);
CGFloat cropW = imageWidth * (cropFrame.size.width / relativeSize.width);
CGFloat cropH = imageHeight * (cropFrame.size.height / relativeSize.height);

这里的cropW和cropH的裁剪区域过大。我不确定是不是精度丢失导致的。

如何计算图片的内存大小

想请教下这个问题,
我先在用的是 CGImageGetHeight(image.CGImage) * CGImageGetBytesPerRow(image.CGImage); 好像不正确

English documentation

Will you support those of us who speaks English in either the documentation or the readme file?

建议:需求建议

能否添加一个配置,让白色截取框放大缩小之后 图片所在的视图保持不动 , 可以随意拖动白色截取框的位置,调整大小呢.感谢作者.

Fatal Exception: CALayerInvalidGeometry CALayer position contains NaN: [177.5 nan]

Fatal Exception: CALayerInvalidGeometry
0 CoreFoundation 0x1e3fabf50 __exceptionPreprocess
1 libobjc.A.dylib 0x1e31a8284 objc_exception_throw
2 CoreFoundation 0x1e3eae25c -[NSCache init]
3 QuartzCore 0x1e8659d50 CA::Layer::set_position(CA::Vec2 const&, bool)
4 QuartzCore 0x1e8659c9c -[CALayer setPosition:]
5 QuartzCore 0x1e8659664 -[CALayer setFrame:]
6 UIKitCore 0x212112200 -[UIView(Geometry) setFrame:]
7 UIKitCore 0x2120e1eb8 -[UIImageView _setViewGeometry:forMetric:]
8 JPImageresizerView 0x1060e7224 -[JPImageresizerView updateSubviewLayouts] (JPImageresizerView.m:355)
9 ****Client 0x10431a088 __52-[CCMCutImageViewController rightNavItemClickAction]_block_invoke (CCMCutImageViewController.m:57)
10 JPImageresizerView 0x1060e87a4 -[JPImageresizerView imageresizerWithComplete:isOriginImageSize:referenceWidth:] (JPImageresizerView.m:545)
11 ****Client 0x104319fe4 -[CCMCutImageViewController rightNavItemClickAction] (CCMCutImageViewController.m:55)
12 libobjc.A.dylib 0x1e31a3900 -[NSObject performSelector:withObject:withObject:]
13 UIKitCore 0x211c697c4 -[UIApplication sendAction:to:from:forEvent:]
14 UIKitCore 0x2113ffccc __45-[_UIButtonBarTargetAction _invoke:forEvent:]_block_invoke
15 UIKitCore 0x2113ffbf8 -[_UIButtonBarTargetAction _invoke:forEvent:]
16 libobjc.A.dylib 0x1e31a3900 -[NSObject performSelector:withObject:withObject:]
17 UIKitCore 0x211c697c4 -[UIApplication sendAction:to:from:forEvent:]
18 UIKitCore 0x2116cfcec -[UIControl sendAction:to:forEvent:]
19 UIKitCore 0x2116d0020 -[UIControl _sendActionsForEvents:withEvent:]
20 UIKitCore 0x2116cefc0 -[UIControl touchesEnded:withEvent:]
21 UIKitCore 0x2118634d8 _UIGestureEnvironmentSortAndSendDelayedTouches
22 UIKitCore 0x21185e0d4 _UIGestureEnvironmentUpdate
23 CoreFoundation 0x1e3f39c54 CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION
24 CoreFoundation 0x1e3f3472c __CFRunLoopDoObservers
25 CoreFoundation 0x1e3f34cb0 __CFRunLoopRun
26 CoreFoundation 0x1e3f344b8 CFRunLoopRunSpecific
27 GraphicsServices 0x1e61e7be8 GSEventRunModal
28 UIKitCore 0x211c68048 UIApplicationMain
29 ****Client 0x104095058 main (main.m:14)
30 libdyld.dylib 0x1e39e9050 start

使用swift构建pod私有库时,引入"JPImageresizerView",编译错误

当我使用swift构建自己的pod私有库时,引入依赖s.dependency 'JPImageresizerView',编译错误,分两大类错误:

  1. 在我自己的xxx.swift文件中使用 import JPImageresizerView,报错”Could not build Objective-C module 'JPImageresizerView'“;
  2. 在JPImageresizerView pod组件内部如:#import <JPImageresizerTypedef.h>等使用尖角号的方式引入头文件的地方,报错:'JPImageresizerTypedef.h' file not found with include; use "quotes" instead

我的尝试
当我尝试把JPImageresizerView组件内所有以尖角号<>引用头文件的方式改为以双引号""后,例如:把#import <JPImageresizerTypedef.h>改为#import "JPImageresizerTypedef.h"后,我的私有pod组件库编译顺利通过了,还请大佬抽时间验证修复下这个问题 @Rogue24

有问题想请求一下

这个是用IOS版本的实现,我对IOS不算懂,但是现在是有一个需求,用Unity来实现,不知道楼主知道怎么实现吗?可以说下大致思路吗?只需要裁剪那一部分,自由拖拽,然后裁剪图片

关于缩放裁剪。

有一张比较宽的图片,我用下面这个方法裁成3:4, 发现图片变小了,应该是没有缩放直接裁剪导致的。

   //将图片裁剪成指定比例(多余部分自动删除)
    func crop(ratio: CGFloat) -> UIImage {
        //计算最终尺寸
        var newSize:CGSize!
        if size.width/size.height > ratio {
            newSize = CGSize(width: size.height * ratio, height: size.height)
        }else{
            newSize = CGSize(width: size.width, height: size.width / ratio)
        }
     
        ////图片绘制区域
        var rect = CGRect.zero
        rect.size.width  = size.width
        rect.size.height = size.height
        rect.origin.x    = (newSize.width - size.width ) / 2.0
        rect.origin.y    = (newSize.height - size.height ) / 2.0
         
        //绘制并获取最终图片
        UIGraphicsBeginImageContext(newSize)
        draw(in: rect)
        let scaledImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
         
        return scaledImage!
    }

想问一下,需要做到demo里编辑页面里选固定尺寸然后生成裁剪后的图片,有提供代码直接操作的方式嘛。

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.