UIImage+ext.m 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. //
  2. // UIImage+ext.m
  3. // PanoramicCameraSDK
  4. //
  5. // Created by 王昭威 on 2023/1/14.
  6. //
  7. #import "UIImage+ext.h"
  8. #import "PCSTools.h"
  9. #import <LenzTensorFlowSDK/LenzTensorFlowSDK.h>
  10. //#import <LenzTensorFlow/LenzTensorFlow.h>
  11. #import <LenzTensorFlowSDK/LenzTensorFlowLib.h>
  12. @implementation UIImage (ext)
  13. - (UIImage *)fixOrientation {
  14. // No-op if the orientation is already correct
  15. if (self.imageOrientation == UIImageOrientationUp) return self;
  16. // We need to calculate the proper transformation to make the image upright.
  17. // We do it in 2 steps: Rotate if Left/Right/Down, and then flip if Mirrored.
  18. CGAffineTransform transform = CGAffineTransformIdentity;
  19. switch (self.imageOrientation) {
  20. case UIImageOrientationDown:
  21. case UIImageOrientationDownMirrored:
  22. transform = CGAffineTransformTranslate(transform, self.size.width, self.size.height);
  23. transform = CGAffineTransformRotate(transform, M_PI);
  24. break;
  25. case UIImageOrientationLeft:
  26. case UIImageOrientationLeftMirrored:
  27. transform = CGAffineTransformTranslate(transform, self.size.width, 0);
  28. transform = CGAffineTransformRotate(transform, M_PI_2);
  29. break;
  30. case UIImageOrientationRight:
  31. case UIImageOrientationRightMirrored:
  32. transform = CGAffineTransformTranslate(transform, 0, self.size.height);
  33. transform = CGAffineTransformRotate(transform, -M_PI_2);
  34. break;
  35. case UIImageOrientationUp:
  36. case UIImageOrientationUpMirrored:
  37. break;
  38. }
  39. switch (self.imageOrientation) {
  40. case UIImageOrientationUpMirrored:
  41. case UIImageOrientationDownMirrored:
  42. transform = CGAffineTransformTranslate(transform, self.size.width, 0);
  43. transform = CGAffineTransformScale(transform, -1, 1);
  44. break;
  45. case UIImageOrientationLeftMirrored:
  46. case UIImageOrientationRightMirrored:
  47. transform = CGAffineTransformTranslate(transform, self.size.height, 0);
  48. transform = CGAffineTransformScale(transform, -1, 1);
  49. break;
  50. case UIImageOrientationUp:
  51. case UIImageOrientationDown:
  52. case UIImageOrientationLeft:
  53. case UIImageOrientationRight:
  54. break;
  55. }
  56. // Now we draw the underlying CGImage into a new context, applying the transform
  57. // calculated above.
  58. CGContextRef ctx = CGBitmapContextCreate(NULL, self.size.width, self.size.height,
  59. CGImageGetBitsPerComponent(self.CGImage), 0,
  60. CGImageGetColorSpace(self.CGImage),
  61. CGImageGetBitmapInfo(self.CGImage));
  62. CGContextConcatCTM(ctx, transform);
  63. switch (self.imageOrientation) {
  64. case UIImageOrientationLeft:
  65. case UIImageOrientationLeftMirrored:
  66. case UIImageOrientationRight:
  67. case UIImageOrientationRightMirrored:
  68. // Grr...
  69. CGContextDrawImage(ctx, CGRectMake(0,0,self.size.height,self.size.width), self.CGImage);
  70. break;
  71. default:
  72. CGContextDrawImage(ctx, CGRectMake(0,0,self.size.width,self.size.height), self.CGImage);
  73. break;
  74. }
  75. // And now we just create a new UIImage from the drawing context
  76. CGImageRef cgimg = CGBitmapContextCreateImage(ctx);
  77. UIImage *img = [UIImage imageWithCGImage:cgimg];
  78. CGContextRelease(ctx);
  79. CGImageRelease(cgimg);
  80. return img;
  81. }
  82. + (nullable UIImage *)sdkImageNamed:(NSString *)name{
  83. return [UIImage imageNamed:name inBundle:[PCSTools sdkBundle] compatibleWithTraitCollection:nil];
  84. }
  85. + (UIImageOrientation)imageOrientationByDeviceOrientation: (UIDeviceOrientation)deviceOrientation isFrontCamera: (BOOL)front{
  86. UIImageOrientation orientation = UIImageOrientationRight;
  87. switch(deviceOrientation){
  88. case UIDeviceOrientationUnknown: {
  89. orientation = front ? UIImageOrientationLeftMirrored : UIImageOrientationRight;
  90. break;
  91. }
  92. case UIDeviceOrientationPortraitUpsideDown: {
  93. orientation = front ? UIImageOrientationRightMirrored : UIImageOrientationLeft;
  94. break;
  95. }
  96. case UIDeviceOrientationLandscapeLeft: {
  97. orientation = front ? UIImageOrientationDownMirrored : UIImageOrientationUp;
  98. break;
  99. }
  100. case UIDeviceOrientationLandscapeRight: {
  101. orientation = front ? UIImageOrientationUpMirrored : UIImageOrientationDown;
  102. break;
  103. }
  104. case UIDeviceOrientationPortrait:
  105. case UIDeviceOrientationFaceUp:
  106. case UIDeviceOrientationFaceDown: {
  107. orientation = front ? UIImageOrientationLeftMirrored : UIImageOrientationRight;
  108. break;
  109. }
  110. }
  111. return orientation;
  112. }
  113. - (float)checkRemake{
  114. CVPixelBufferRef buf = [self toCVPixelBufferRef];
  115. return [self checkRemakeForFrame:buf];
  116. }
  117. - (float)checkRemakeForFrame: (CVPixelBufferRef)frameBuffer{
  118. if(frameBuffer == nil){
  119. return 0;
  120. }
  121. NSString* path = [[PCSTools sdkBundle] pathForResource:@"moire_mobilenetv2_79" ofType:@"tflite"];
  122. LenzTensorFlowLib* lib = [[LenzTensorFlowLib alloc] initWithModelPath:path labels:@[@"origin", @"remake"]];
  123. NSDictionary * ret = [lib runModelOnFrame:frameBuffer];
  124. float value = 0;
  125. if(ret[@"remake"] != nil){
  126. value = [ret[@"remake"] floatValue];
  127. }
  128. return value;
  129. }
  130. - (CVPixelBufferRef)toCVPixelBufferRef
  131. {
  132. CGImageRef image = [self CGImage];
  133. NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
  134. [NSNumber numberWithBool:YES], kCVPixelBufferCGImageCompatibilityKey,
  135. [NSNumber numberWithBool:YES], kCVPixelBufferCGBitmapContextCompatibilityKey,
  136. nil];
  137. CVPixelBufferRef pxbuffer = NULL;
  138. CGFloat frameWidth = CGImageGetWidth(image);
  139. CGFloat frameHeight = CGImageGetHeight(image);
  140. CVReturn status = CVPixelBufferCreate(kCFAllocatorDefault,
  141. frameWidth,
  142. frameHeight,
  143. kCVPixelFormatType_32ARGB,
  144. (__bridge CFDictionaryRef) options,
  145. &pxbuffer);
  146. NSParameterAssert(status == kCVReturnSuccess && pxbuffer != NULL);
  147. CVPixelBufferLockBaseAddress(pxbuffer, 0);
  148. void *pxdata = CVPixelBufferGetBaseAddress(pxbuffer);
  149. NSParameterAssert(pxdata != NULL);
  150. CGColorSpaceRef rgbColorSpace = CGColorSpaceCreateDeviceRGB();
  151. CGContextRef context = CGBitmapContextCreate(pxdata,
  152. frameWidth,
  153. frameHeight,
  154. 8,
  155. CVPixelBufferGetBytesPerRow(pxbuffer),
  156. rgbColorSpace,
  157. (CGBitmapInfo)kCGImageAlphaNoneSkipFirst);
  158. NSParameterAssert(context);
  159. CGContextConcatCTM(context, CGAffineTransformIdentity);
  160. CGContextDrawImage(context, CGRectMake(0,
  161. 0,
  162. frameWidth,
  163. frameHeight),
  164. image);
  165. CGColorSpaceRelease(rgbColorSpace);
  166. CGContextRelease(context);
  167. CVPixelBufferUnlockBaseAddress(pxbuffer, 0);
  168. return pxbuffer;
  169. }
  170. - (instancetype)initWithBuffer:(CMSampleBufferRef)sampledBuffer isFrontCamera: (BOOL)front motionOrientation:(UIDeviceOrientation)motionOrientation{
  171. CVImageBufferRef pixelBuffer = CMSampleBufferGetImageBuffer(sampledBuffer);
  172. if(pixelBuffer == NULL){
  173. return nil;
  174. }
  175. CVPixelBufferLockBaseAddress(pixelBuffer, kCVPixelBufferLock_ReadOnly);
  176. void* baseAddress = CVPixelBufferGetBaseAddress(pixelBuffer);
  177. size_t width = CVPixelBufferGetWidth(pixelBuffer);
  178. size_t height = CVPixelBufferGetHeight(pixelBuffer);
  179. size_t bytesPerRow = CVPixelBufferGetBytesPerRow(pixelBuffer);
  180. CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
  181. CGContextRef context = CGBitmapContextCreate(baseAddress, width, height, 8, bytesPerRow, colorSpace, kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Little);
  182. if(context == NULL){
  183. return nil;
  184. }
  185. CGImageRef imgRef = CGBitmapContextCreateImage(context);
  186. if(imgRef == NULL){
  187. return nil;
  188. }
  189. UIImageOrientation orientation = [UIImage imageOrientationByDeviceOrientation:motionOrientation isFrontCamera:front];
  190. self = [self initWithCGImage:imgRef scale:1 orientation:orientation];
  191. CVPixelBufferUnlockBaseAddress(pixelBuffer, kCVPixelBufferLock_ReadOnly);
  192. CGImageRelease(imgRef);
  193. return self;
  194. }
  195. @end