티스토리 뷰
Core Image Filter
코어 이미지 필터는 입력 이미지와 필터의 동작을 설정하는 옵션을 매개변수로 사용한다.
적용할 필터의 리스트를 지정하면 각필터를 지정했을 때
계산을 실행하는게 아니라 최종 출력 이미지를 요청할 때만
이 필터들을 한꺼번에 모두 적용한다.
필터 카테고리와 필터
코어 이미지 필터는 내부적으로 카테고리 단위로 구성된다.
한 필터는 하나 이상의 카테고리에 속할 수 있다.
카테고리를 이용해서 원하는 작업에 어떤 코어 이미지 필터들이 필요한지 결정할 수 있다.
CategoryKey 를 이용하여 CIFilterArray 를 구할 수 있다.
(https://developer.apple.com/library/content/documentation/GraphicsImaging/Reference/CoreImageFilterReference/)
self.categoryList = @{
@"Blur" : kCICategoryBlur,
@"Color Adjustment" : kCICategoryColorAdjustment,
@"Color Effect" : kCICategoryColorEffect,
@"Composite" : kCICategoryCompositeOperation,
@"Distortion" : kCICategoryDistortionEffect,
@"Generator" : kCICategoryGenerator,
@"Geometry Adjustment" : kCICategoryGeometryAdjustment,
@"Gradient" : kCICategoryGradient,
@"Halftone Effect" : kCICategoryHalftoneEffect,
@"Reduction" : kCICategoryReduction,
@"Sharpen" : kCICategorySharpen,
@"Stylize" : kCICategoryStylize,
@"Tile" : kCICategoryTileEffect,
@"Transition" : kCICategoryTransition
};
self.categoryKeys = [self.categoryList allKeys];
self.filterNameArray = [CIFilter filterNamesInCategory:self.selectedCategory];
각각의 filter 값에 대한 설명은 위 document 에 아주 상세히 설명되어 있으므로 사용법만 알아본다.
필터 속성
모든 CIFilter 객체는 attributes 라는 딕셔너리를 프로퍼티로 갖고있다.
이 dictionary 객체는 필터와 설정에 필요한 모든 정보를 담고있다.
CIFilter
NSArray<NSString *> *inputKeys;
NSArray<NSString *> *outputKeys;
NSDictionary<NSString *, id (NSDictionary *)> *attributes;
NSString *attributeName = [[self.selectedFilter inputKeys] objectAtIndex:indexPath.row];
NSDictionary *attributeInfo = [[self.selectedFilter attributes] valueForKey:attributeName];
inputKeys 는 attributeName array 이다.
attibuteInfo 는 attributes 를 이용하여 얻어올 수 있다.
attributeInfo 를 이용하면 속성이 어떤 타입인지,
속성의 정보를 표현하는 데 어떤 클래스를 사용해야하는지 알 수 있다.
모든 필터가 속성 타입과 속성 클래스를 동일한 방식으로 지정하지 않는다.
어떤 필터는 kCIAttributeTypeColor 라는 속성 타입만을 지정할 수 있고,
어떤 필터는 CIColor 라는 속성 클래스만을 지정할 수 있다.
따라서 attributeType 과 attributeClass 를 사용하여 사용자가 조절할 수 있는 값을 사용한다.
- (NSString *)getCellIdentifierForAttributeType:(NSDictionary *)attributeInfo
{
NSString *attributeType = @"";
if ([attributeInfo objectForKey:kCIAttributeType]) {
attributeType = [attributeInfo objectForKey:kCIAttributeType];
}
NSString *attributeClass =
[attributeInfo objectForKey:kCIAttributeClass];
NSString *cellIdentifier = @"";
if ([attributeType isEqualToString:kCIAttributeTypeColor] ||
[attributeClass isEqualToString:@"CIColor"])
{
cellIdentifier = kICSInputColorCellIdentifier;
}
if ([attributeType isEqualToString:kCIAttributeTypeImage] ||
[attributeClass isEqualToString:@"CIImage"])
{
cellIdentifier = kICSInputImageCellIdentifier;
}
if ([attributeType isEqualToString:kCIAttributeTypeScalar] ||
[attributeType isEqualToString:kCIAttributeTypeDistance] ||
[attributeType isEqualToString:kCIAttributeTypeAngle] ||
[attributeType isEqualToString:kCIAttributeTypeTime])
{
cellIdentifier = kICSInputNumberCellIdentifier;
}
if ([attributeType isEqualToString:kCIAttributeTypePosition] ||
[attributeType isEqualToString:kCIAttributeTypeOffset] ||
[attributeType isEqualToString:kCIAttributeTypeRectangle] ||
[attributeClass isEqualToString:@"CIVector"])
{
cellIdentifier = kICSInputVectorCellIdentifier;
}
if ([attributeClass isEqualToString:@"NSValue"])
{
cellIdentifier = kICSInputTransformCellIdentifier;
}
return cellIdentifier;
}
위 정보는 cellForRow 에서 attributeInfo 를 이용하여 호출하면 된다.
이미지 객체 초기화
코어 이미지에서 이미지에 필터를 적용하려면 CIImage 클래스의 객체로 만들어야한다.
UIImage 객체로부터 CIImage 객체를 얻으려면, CGImage 로 변환 후 이를 다시 CIImage 로 변환해야한다.
( UIImage -> CGImage -> CIImage )
CGImageRef inputImageRef = [sourceImage CGImage];
CIImage *inputImage = [CIImage imageWithCGImage:inputImageRef];
필터링한 이미지 그리기
필터링한 이미지를 출력(UIImage 화) 하려면 필터의 속성 중에서 outputImage 객체를 요청한다.
이 객체를 컨텍스트, 이미지, 비트맵, 픽셀 버퍼 중 출력하고 싶은 대상과
대응하는 적절한 메소드를 호출하면된다.
이 시점에서는 이미 입력 이미지에 대해 필터 적용을 끝내고 출력이미지 객체가 생성돼 있어야한다.
일반적으로는 context 를 프로퍼티로서 미리 초기화하는 게 일반적이다.
- (IBAction)previewButtonTouched:(id)sender
{
CIContext *context = [CIContext contextWithOptions:nil];
CIFilter *filter = self.selectedFilter;
CIImage *resultImage = [filter valueForKey:kCIOutputImageKey];
CGRect imageRect = CGRectMake(0, 0, 200, 200);
CGImageRef resultCGImage =
[context createCGImage:resultImage fromRect:imageRect];
UIImage *resultUIImage =
[UIImage imageWithCGImage:resultCGImage];
[self.previewImageView setImage:resultUIImage];
}
컨텍스트를 초기화 한 후 filter 를 통해 outputImage 에 대한 참조를 얻는데,
필터 중에는 입력보다 훨씬 더 커지는 결과 이미지를 생성하는 것도 있다. (Generator Category)
따라서 원하는 크기를 지정할 때 (imageRect) 고려가 필요하다.
여러개의 필터 적용하기
CIFilter *lastFilter = [self.filterArray lastObject];
if (lastFilter) {
if ([[filter inputKeys] containsObject:@"inputImage"] ) {
[filter setValue:[lastFilter outputImage]
forKey:@"inputImage"];
}
}
[self.filterArray addObject:filter];
lastFilter 를 구해 와 inputImage 에 outputImage 를 set 해준다.
CIContext *context = [CIContext contextWithOptions:nil];
CIImage *resultImage = [filter valueForKey:kCIOutputImageKey];
CGImageRef resultCGImage = [context createCGImage:resultImage fromRect:CGRectMake(0, 0, 200, 200)];
UIImage *resultUIImage = [UIImage imageWithCGImage:resultCGImage];
[self.resultImageView setImage:resultUIImage];
코어 이미지는 필터링에 필요한 계산을 최소화하기 위해
자동으로 필터 체인을 최적화한다.
각 단계의 필터를 개별적으로 처리하지 않고
모든 필터에서 필요한 수학 계산을 합쳐서 한꺼번에 필터를 적용한다.
'iOS 개발 > iOS' 카테고리의 다른 글
[iOS] TextKit 의 사용 (탐지 및 글씨 제외영역 잡기) (0) | 2016.12.02 |
---|---|
[iOS] 안면 인식 (CIDetector) (0) | 2016.11.29 |
[iOS] UIImage 의 사용 (load, imageView, picker, resize, stretch) (0) | 2016.11.28 |
[iOS] UIImage, CIImage, CGImage 의 차이점 (0) | 2016.11.25 |
[iOS] KeyChain 을 이용한 데이터 보호 및 앱 간 공유 (0) | 2016.11.25 |
- Total
- Today
- Yesterday
- ios
- RunLoop
- NSManagedObject
- applicationWillResignActive
- NSManagedObjectContext
- docker
- CIImage
- HTTP
- UIView
- Swift 3
- Arc
- workerThread
- EffectiveObjectiveC
- AWS
- CGImage
- set
- dictionary
- string
- NSManagedObjectModel
- 꺼내먹어요
- optional
- Swift3
- Swfit
- delegate
- 읽기 좋은 코드가 좋은 코드다
- Swift 3.0
- Block
- thread
- Swift
- coredata
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |