FUImageRenderViewController.m 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  1. //
  2. // FUImageRenderViewController.m
  3. // FULiveDemo
  4. //
  5. // Created by 项林平 on 2022/8/8.
  6. //
  7. #import "FUImageRenderViewController.h"
  8. @interface FUImageRenderViewController ()
  9. @property (nonatomic, strong) FUGLDisplayView *renderView;
  10. @property (nonatomic, strong) UIButton *downloadButton;
  11. @property (nonatomic, strong) UILabel *noTrackLabel;
  12. @property (nonatomic, strong) UILabel *tipLabel;
  13. @property (nonatomic, strong) FUImageRenderViewModel *viewModel;
  14. @end
  15. @implementation FUImageRenderViewController
  16. #pragma mark - Initializer
  17. - (instancetype)initWithViewModel:(FUImageRenderViewModel *)viewModel {
  18. self = [super init];
  19. if (self) {
  20. self.viewModel = viewModel;
  21. self.viewModel.delegate = self;
  22. }
  23. return self;
  24. }
  25. #pragma mark - Life cycle
  26. - (void)viewDidLoad {
  27. [super viewDidLoad];
  28. [self configureUI];
  29. [self.viewModel start];
  30. [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationWillResignActive) name:UIApplicationWillResignActiveNotification object:nil];
  31. [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationDidBecomeActive) name:UIApplicationDidBecomeActiveNotification object:nil];
  32. }
  33. - (void)viewWillAppear:(BOOL)animated {
  34. [super viewWillAppear:animated];
  35. // 添加点位测试开关
  36. if ([FURenderKitManager sharedManager].showsLandmarks) {
  37. [FULandmarkManager show];
  38. }
  39. }
  40. - (void)viewWillDisappear:(BOOL)animated {
  41. [super viewWillDisappear:animated];
  42. // 移除点位测试开关
  43. if ([FURenderKitManager sharedManager].showsLandmarks) {
  44. [FULandmarkManager dismiss];
  45. }
  46. }
  47. - (void)dealloc {
  48. [self.viewModel stop];
  49. [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationWillResignActiveNotification object:nil];
  50. [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidBecomeActiveNotification object:nil];
  51. }
  52. #pragma mark - UI
  53. - (void)configureUI {
  54. self.view.backgroundColor = [UIColor blackColor];
  55. [self.view addSubview:self.renderView];
  56. [self.renderView mas_makeConstraints:^(MASConstraintMaker *make) {
  57. make.leading.trailing.equalTo(self.view);
  58. if (@available(iOS 11.0, *)) {
  59. make.top.equalTo(self.view.mas_safeAreaLayoutGuideTop);
  60. if(FUDeviceIsiPhoneXStyle()) {
  61. make.bottom.equalTo(self.view.mas_safeAreaLayoutGuideBottom).mas_offset(-50);
  62. } else {
  63. make.bottom.equalTo(self.view.mas_safeAreaLayoutGuideBottom);
  64. }
  65. } else {
  66. make.top.equalTo(self.view.mas_top);
  67. make.bottom.equalTo(self.view.mas_bottom);
  68. }
  69. make.leading.trailing.equalTo(self.view);
  70. }];
  71. UIButton *backButton = [UIButton buttonWithType:UIButtonTypeCustom];
  72. [backButton setImage:[UIImage imageNamed:@"back_item"] forState:UIControlStateNormal];
  73. [backButton addTarget:self action:@selector(backAction:) forControlEvents:UIControlEventTouchUpInside];
  74. [self.view addSubview:backButton];
  75. [backButton mas_makeConstraints:^(MASConstraintMaker *make) {
  76. if (@available(iOS 11.0, *)) {
  77. make.top.equalTo(self.view.mas_safeAreaLayoutGuideTop).offset(20);
  78. } else {
  79. make.top.equalTo(self.view.mas_top).offset(30);
  80. }
  81. make.leading.equalTo(self.view.mas_leading).offset(10);
  82. make.size.mas_offset(CGSizeMake(44, 44));
  83. }];
  84. [self.view addSubview:self.noTrackLabel];
  85. [self.noTrackLabel mas_makeConstraints:^(MASConstraintMaker *make) {
  86. make.center.equalTo(self.view);
  87. }];
  88. [self.view addSubview:self.tipLabel];
  89. [self.tipLabel mas_makeConstraints:^(MASConstraintMaker *make) {
  90. make.centerY.equalTo(self.view.mas_centerY).mas_offset(24);
  91. make.centerX.equalTo(self.view);
  92. make.width.mas_equalTo(300);
  93. make.height.mas_equalTo(32);
  94. }];
  95. [self.view addSubview:self.downloadButton];
  96. [self.downloadButton mas_makeConstraints:^(MASConstraintMaker *make) {
  97. make.bottom.equalTo(self.view.mas_bottom).offset(-self.viewModel.downloadButtonBottomConstant - 10);
  98. make.centerX.equalTo(self.view);
  99. make.size.mas_offset(CGSizeMake(85, 85));
  100. }];
  101. }
  102. #pragma mark - Instance methods
  103. - (void)updateBottomConstraintsOfDownloadButton:(CGFloat)constraints {
  104. [self.downloadButton mas_updateConstraints:^(MASConstraintMaker *make) {
  105. make.bottom.equalTo(self.view.mas_bottom).mas_offset(-constraints-10);
  106. }];
  107. [UIView animateWithDuration:0.15 animations:^{
  108. [self.view layoutIfNeeded];
  109. }];
  110. }
  111. #pragma mark - Event response
  112. - (void)backAction:(UIButton *)sender {
  113. [self.navigationController popViewControllerAnimated:YES];
  114. }
  115. - (void)downloadAction:(UIButton *)sender {
  116. @FUWeakify(self)
  117. self.viewModel.captureImageHandler = ^(UIImage * _Nonnull image) {
  118. @FUStrongify(self)
  119. dispatch_async(dispatch_get_main_queue(), ^{
  120. UIImageWriteToSavedPhotosAlbum(image, self, @selector(image:didFinishSavingWithError:contextInfo:), NULL);
  121. });
  122. };
  123. }
  124. - (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo {
  125. if (error) {
  126. [FUTipHUD showTips:FULocalizedString(@"保存图片失败") dismissWithDelay:1.5];
  127. } else {
  128. [FUTipHUD showTips:FULocalizedString(@"图片已保存到相册") dismissWithDelay:1.5];
  129. }
  130. }
  131. - (void)applicationWillResignActive {
  132. [self.viewModel stop];
  133. }
  134. - (void)applicationDidBecomeActive {
  135. [self.viewModel start];
  136. }
  137. #pragma mark - FUImageRenderViewModelDelegate
  138. - (void)imageRenderDidOutputImageBuffer:(FUImageBuffer)imageBuffer {
  139. [self.renderView displayImageData:imageBuffer.buffer0 withSize:imageBuffer.size];
  140. }
  141. - (void)imageRenderShouldCheckDetectingStatus:(FUDetectingParts)parts {
  142. @autoreleasepool {
  143. BOOL detectingResult = YES;
  144. switch (parts) {
  145. case FUDetectingPartsFace:
  146. detectingResult = [FURenderKitManager faceTracked];
  147. break;
  148. case FUDetectingPartsHuman:
  149. detectingResult = [FURenderKitManager humanTracked];
  150. break;
  151. case FUDetectingPartsHand:
  152. detectingResult = [FURenderKitManager handTracked];
  153. break;
  154. default:
  155. break;
  156. }
  157. dispatch_async(dispatch_get_main_queue(), ^{
  158. self.noTrackLabel.hidden = detectingResult;
  159. if (!detectingResult) {
  160. self.noTrackLabel.text = parts == FUDetectingPartsFace ? FULocalizedString(@"未检测到人脸") : (parts == FUDetectingPartsHuman ? FULocalizedString(@"未检测到人体") : FULocalizedString(@"未检测到手势"));
  161. }
  162. });
  163. }
  164. }
  165. #pragma mark - Getters
  166. - (UIButton *)downloadButton {
  167. if (!_downloadButton) {
  168. _downloadButton = [UIButton buttonWithType:UIButtonTypeCustom];
  169. _downloadButton.frame = CGRectMake(CGRectGetWidth(self.view.bounds) / 2.0 - 42.5, CGRectGetHeight(self.view.bounds) - 85 - FUHeightIncludeBottomSafeArea(10), 85, 85);
  170. _downloadButton.backgroundColor = [UIColor whiteColor];
  171. _downloadButton.layer.cornerRadius = 42.5;
  172. [_downloadButton setBackgroundImage:[UIImage imageNamed:@"render_save"] forState:UIControlStateNormal];
  173. [_downloadButton addTarget:self action:@selector(downloadAction:) forControlEvents:UIControlEventTouchUpInside];
  174. }
  175. return _downloadButton;
  176. }
  177. - (UILabel *)noTrackLabel {
  178. if (!_noTrackLabel) {
  179. _noTrackLabel = [[UILabel alloc] init];
  180. _noTrackLabel.textColor = [UIColor whiteColor];
  181. _noTrackLabel.font = [UIFont systemFontOfSize:17];
  182. _noTrackLabel.text = FULocalizedString(@"未检测到人脸");
  183. _noTrackLabel.hidden = YES;
  184. }
  185. return _noTrackLabel;
  186. }
  187. - (UILabel *)tipLabel {
  188. if (!_tipLabel) {
  189. _tipLabel = [[UILabel alloc] init];
  190. _tipLabel.textColor = [UIColor whiteColor];
  191. _tipLabel.font = [UIFont systemFontOfSize:32];
  192. _tipLabel.textAlignment = NSTextAlignmentCenter;
  193. _tipLabel.hidden = YES;
  194. }
  195. return _tipLabel;
  196. }
  197. - (FUGLDisplayView *)renderView {
  198. if (!_renderView) {
  199. _renderView = [[FUGLDisplayView alloc] initWithFrame:self.view.bounds];
  200. _renderView.contentMode = FUGLDisplayViewContentModeScaleAspectFit;
  201. }
  202. return _renderView;
  203. }
  204. #pragma mark - Override methods
  205. - (BOOL)prefersStatusBarHidden {
  206. return !FUDeviceIsiPhoneXStyle();
  207. }
  208. - (UIStatusBarStyle)preferredStatusBarStyle {
  209. return UIStatusBarStyleLightContent;
  210. }
  211. @end