iOS 에서 큰 크기 의 그림 의 회전 과 크기 조정 인 스 턴 스 상세 설명

머리말
아이 폰 의 하드웨어 성능 제한 으로 아이 폰 6s 가 시 작 될 때 까지 최대 메모 리 를 2G 로 확장 했다.
그렇다 고 해서 응용 프로그램 이 사용 할 수 있 는 공간 이 2G 인 것 은 아니다.
10000 x 10000 의 그림 이 UIImageJPEG Representation 방법 으로 그림 을 메모리 데이터 로 변환 하면 피크 값 변동 이 있 습 니 다.
이곳 의 피크 수 치 는 사실 그림 이 압축 을 풀 때 발생 하 는 비트 맵 데이터 가 공간 을 차지 한 후에 야 우리 가 조작 할 수 있 는 NSData 로 바 뀌 었 다.
그 계산 공식 은 W x H x 4/1024/1024 즉 10000 x 10000 x4/1024/1024=381.4(M)이다.
이곳 은 381 M 의 소모 가 발생 하여 제때에 회수 되 지만 생각해 보면 그림 의 크기 가 크 고 수량 이 많 을 때 이상 이 발생 하기 쉽다.
본 고 는 iOS 의 큰 사이즈 그림 회전 과 크기 조정 에 관 한 내용 을 상세 하 게 소개 하고 참고 학습 을 제공 하 며 더 이상 말 하지 않 겠 습 니 다.다음은 구체 적 인 조작 을 말씀 드 리 겠 습 니 다.
빙빙 돌다
UIImage 대상 을 회전 시 키 면 프로젝트 를 할 때 반드시 UIImage 와 같은 방식 이 있 을 것 이 라 고 믿 습 니 다.
CGContextDrawImage 를 통 해 그림 그리 기

+ (UIImage *)image:(UIImage *)image rotation:(UIImageOrientation)orientation {

 long double rotate = 0.0;
 CGRect rect;
 float translateX = 0;
 float translateY = 0;
 float scaleX = 1.0;
 float scaleY = 1.0;

 switch (orientation) {
 case UIImageOrientationLeft:
 rotate = M_PI_2;
 rect = CGRectMake(0, 0, image.size.height, image.size.width);
 translateX = 0;
 translateY = -rect.size.width;
 scaleY = rect.size.width/rect.size.height;
 scaleX = rect.size.height/rect.size.width;
 break;
 default:
 rotate = 0.0;
 rect = CGRectMake(0, 0, image.size.width, image.size.height);
 translateX = 0;
 translateY = 0;
 break;
 }

 UIGraphicsBeginImageContext(rect.size);
 CGContextRef context = UIGraphicsGetCurrentContext();
 // CTM  
 CGContextTranslateCTM(context, 0.0, rect.size.height);
 CGContextScaleCTM(context, 1.0, -1.0);
 CGContextRotateCTM(context, rotate);
 CGContextTranslateCTM(context, translateX, translateY);

 CGContextScaleCTM(context, scaleX, scaleY);
 //    
 CGContextDrawImage(context, CGRectMake(0, 0, rect.size.width, rect.size.height), image.CGImage);
 UIImage *newPic = UIGraphicsGetImageFromCurrentImageContext();
 return newPic;
} 
여기에 새로운 그림 크기 공간 을 만 들 고 다시 그 리 는 것 이 문제 입 니 다.그림 의 크기 가 너무 클 때 메모리 사용량 이 너무 높 은 경우 가 발생 할 수 있 습 니 다.
다음은 그림 에 필 터 를 추가 하 는 방법 을 소개 한다.
작업 대상 이 그림 인 이상 각종 필터 가 전시 된다.시스템 은 우리 에 게 몇 백 여 종의 필 터 를 제 공 했 는 지,이곳 의 필 터 는 단지 색깔 등 상태 에 변화 가 발생 하지 않 는 다.
그 중 에 우리 가 필요 로 하 는 필터 키 input Transform 이 있 습 니 다.

+ (UIImage *)getRotationImage:(UIImage *)image rotation:(CGFloat)rotation {

 CIImage *ciImage = [[CIImage alloc] initWithImage:image];
 CIFilter *filter = [CIFilter filterWithName:@"CIAffineTransform" keysAndValues:kCIInputImageKey, ciImage, nil];

 [filter setDefaults];
 CGAffineTransform transform = CATransform3DGetAffineTransform([self rotateTransform:CATransform3DIdentity clockwise:NO angle:rotation]);
 [filter setValue:[NSValue valueWithBytes:&transform objCType:@encode(CGAffineTransform)] forKey:@"inputTransform"];

 //        
 CIContext *context = [CIContext contextWithOptions:@{kCIContextUseSoftwareRenderer : @(NO)}];
 CIImage *outputImage = [filter outputImage];
 CGImageRef cgImage = [context createCGImage:outputImage fromRect:[outputImage extent]];

 UIImage *result = [UIImage imageWithCGImage:cgImage];

 CGImageRelease(cgImage);

 return result;
}
+ (CATransform3D)rotateTransform:(CATransform3D)initialTransform clockwise:(BOOL)clockwise angle:(CGFloat)angle {

 CGFloat arg = angle*M_PI / 180.0f;
 if(!clockwise){
 arg *= -1;
 }
 //    
 CATransform3D transform = initialTransform;
 transform = CATransform3DRotate(transform, arg, 0, 0, 1);
 CGFloat _flipState1 = 0;
 CGFloat _flipState2 = 0;
 transform = CATransform3DRotate(transform, _flipState1*M_PI, 0, 1, 0);
 transform = CATransform3DRotate(transform, _flipState2*M_PI, 1, 0, 0);

 return transform;
} 
이런 조작 을 통 해 GPU 를 이용 하여 이미지 조작 을 할 수 있어 소 모 를 어느 정도 줄 이 고 자원 을 절약 할 수 있다.
크기 조정
그림 이 매우 큰 이상 우 리 는 크기 를 조정 하 는 방식 으로 그림 의 사 이 즈 를 줄 이 고 메모리 소 모 를 줄 이 며 이상 위험 을 낮 출 수 있다.
저 희 는 보통 UIImage 가 제공 하 는 시스템 방법 인 drawingRect 와 그 일련의 방법 으로 그림 크기 를 조정 합 니 다.
그러나 이런 조작의 결함 은 처음에 소 개 된 회전 과 마찬가지 로 실질 적 으로 그림 을 다시 그 리 는 것 이다.
그림 그리 기 를 통 해 그림 크기 조정 하기

+ (UIImage *)image:(UIImage *)image transformtoSize:(CGSize)Newsize {
 //     bitmap context
 UIGraphicsBeginImageContext(Newsize);
 //          
 [image drawInRect:CGRectMake(0, 0, Newsize.width, Newsize.height)];
 //    context             
 UIImage *TransformedImg=UIGraphicsGetImageFromCurrentImageContext();
 //     context   
 UIGraphicsEndImageContext();
 //             
 return TransformedImg;
}
여 기 는 메모리 소모 입 니 다.그림 을 보면 큰 그림 에 대해 크기 를 조정 할 때 메모리 소모 피크 수 치 는 426 M 에 달 하고 시간 은 1.5s 정도 인 것 을 알 수 있다.
우리 가 사용 하 는 휴대 전 화 는 아이 폰 X 이기 때문에 더 낮은 장치 에서 이것 이 얼마나 큰 손실 인지 이상 이 발생 하기 쉽다.

위의 방법 이 매우 큰 손실 을 입 었 으 니,우 리 는 다른 방식 을 보 자.
메모리 소모 부터 볼 게 요.

그림 을 통 해 알 수 있 듯 이 그림 크기 를 조정 할 때 메모리 가 소폭 증가 하고 발생 하 는 소 모 는 18M 이 며 소모 시간 도 1.5s 정도 이다.
이런 효 과 는 매우 현저 하 다.다음은 코드 를 보 겠 습 니 다.

+(UIImage *)resizeImage:(UIImage *)image toSize:(CGSize)size {

 CIImage *ciImage = [[CIImage alloc] initWithImage:image];
 //    input image     
 CIFilter *filter = [CIFilter filterWithName:@"CIAffineTransform" keysAndValues:kCIInputImageKey, ciImage, nil];
 //         
 [filter setDefaults];

 //      
 CGFloat scale = 1;
 if (size.width != CGFLOAT_MAX) {
 scale = (CGFloat) size.width / image.size.width;
 } else if (size.height != CGFLOAT_MAX) {
 scale = (CGFloat) size.height / image.size.height;
 }

 //    
 CGAffineTransform transform = CGAffineTransformMakeScale(scale, scale);
 [filter setValue:[NSValue valueWithBytes:&transform objCType:@encode(CGAffineTransform)] forKey:@"inputTransform"];

 //  GPU        
 CIContext *context = [CIContext contextWithOptions:@{kCIContextUseSoftwareRenderer : @(NO)}];
 //        
 CIImage *outputImage = [filter outputImage];
 CGImageRef cgImage = [context createCGImage:outputImage fromRect:[outputImage extent]];
 //  UIImage   ,     
 UIImage *result = [UIImage imageWithCGImage:cgImage];

 CGImageRelease(cgImage);

 return result;
}
우리 가 이곳 에서 사용 하 는 것 과 회전 이 같은 방식 이라는 것 을 알 수 있다.그림 에 필 터 를 추가 하면 우리 의 수 요 를 안전하게 실현 할 수 있다.
총결산
1.대형 사진 조작 에 대해 이런 사고방식 을 사용 할 수 있다.선생님 은 사이즈 가 작은 미리 보기 그림 을 만 든 다음 에 각종 조작 을 하면 자원 소 모 를 줄 일 수 있다.
2.코어 이미지.framework 를 통 해 이미지 처 리 를 한다.
3.코어 이미지.framework 에 대한 이 해 는 그림 과 동 영상 에 보 이 는 필 터 를 추가 할 수 있 을 뿐 이 필터 도 크기 조정 과 회전 을 지원 할 줄 은 몰 랐 다.
? 왜 CoreImage.framework 의 방식 이 안전 합 니까?
이 프레임 워 크 는 iOS 5 부터 사용 에 들 어가 CoreGraphics.framework,CoreVideo.framework,Image I/O.framework 를 통 해 데이터 처 리 를 하고,
CPU 와 GPU 사이 에서 연산 방식 을 자 유 롭 게 전환 할 수 있 습 니 다.
GPU 를 최대한 이용 하여 계산 하여 메모리 소 모 를 줄 일 수 있 습 니 다.
영상 을 실시 간 으로 필터 처리 할 수도 있다.
네 이 티 브 를 통 해 UIView 를 transform 작업 할 수 없 을 때 CoreImage.framework 는 친구 가 될 것 입 니 다.
가장 직접적인
Core Image is an image processing and analysis technology designed to provide near real-time processing for still and video images. It operates on image data types from the Core Graphics, Core Video, and Image I/O frameworks, using either a GPU or CPU rendering path. Core Image hides the details of low-level graphics processing by providing an easy-to-use application programming interface (API). You don't need to know the details of OpenGL, OpenGL ES, or Metal to leverage the power of the GPU, nor do you need to know anything about Grand Central Dispatch (GCD) to get the benefit of multicore processing. Core Image handles the details for you.
그것 은 이미 너 를 도와 모든 물건 을 다 처 리 했 으 니 대담 하 게 써 라.
문서.  ( 코드 주소
총결산
이상 은 이 글 의 전체 내용 입 니 다.본 논문 의 내용 이 여러분 의 학습 이나 업무 에 어느 정도 참고 학습 가치 가 있 기 를 바 랍 니 다.궁금 한 점 이 있 으 시 면 댓 글 을 남 겨 주 셔 서 저희 에 대한 지지 에 감 사 드 립 니 다.

좋은 웹페이지 즐겨찾기