Skip to content

Instantly share code, notes, and snippets.

@pixnbit
Last active May 3, 2018 01:59
Show Gist options
  • Save pixnbit/5747004 to your computer and use it in GitHub Desktop.
Save pixnbit/5747004 to your computer and use it in GitHub Desktop.
Category on CIFaceFeature to convert CGPoint and CGRect with respect to UIImageOrientation, also with handy helpers to convert locations inside of a given UIView size.
//
// CIFaceFeature+UIImageOrientation.h
//
//
// Created by Xiaochao Yang on 6/9/13.
// Copyright (c) 2013 Xiaochao Yang. All rights reserved.
//
#import <CoreImage/CoreImage.h>
@interface CIFaceFeature (UIImageOrientation)
// Get converted features with respect to the imageOrientation property
- (CGPoint) leftEyePositionForImage:(UIImage *)image;
- (CGPoint) rightEyePositionForImage:(UIImage *)image;
- (CGPoint) mouthPositionForImage:(UIImage *)image;
- (CGRect) boundsForImage:(UIImage *)image;
// Get normalized features (0-1) with respect to the imageOrientation property
- (CGPoint) normalizedLeftEyePositionForImage:(UIImage *)image;
- (CGPoint) normalizedRightEyePositionForImage:(UIImage *)image;
- (CGPoint) normalizedMouthPositionForImage:(UIImage *)image;
- (CGRect) normalizedBoundsForImage:(UIImage *)image;
// Get feature location inside of a given UIView size with respect to the imageOrientation property
- (CGPoint) leftEyePositionForImage:(UIImage *)image inView:(CGSize)viewSize;
- (CGPoint) rightEyePositionForImage:(UIImage *)image inView:(CGSize)viewSize;
- (CGPoint) mouthPositionForImage:(UIImage *)image inView:(CGSize)viewSize;
- (CGRect) boundsForImage:(UIImage *)image inView:(CGSize)viewSize;
@end
//
// CIFaceFeature+UIImageOrientation.m
//
//
// Created by Xiaochao Yang on 6/9/13.
// Copyright (c) 2013 Xiaochao Yang. All rights reserved.
//
#import "CIFaceFeature+UIImageOrientation.h"
@implementation CIFaceFeature (UIImageOrientation)
- (CGPoint) leftEyePositionForImage:(UIImage *)image{
return [self pointForImage:image fromPoint:self.leftEyePosition];
}
- (CGPoint) rightEyePositionForImage:(UIImage *)image{
return [self pointForImage:image fromPoint:self.rightEyePosition];
}
- (CGPoint) mouthPositionForImage:(UIImage *)image{
return [self pointForImage:image fromPoint:self.mouthPosition];
}
- (CGRect) boundsForImage:(UIImage *)image{
return [self boundsForImage:image fromBounds:self.bounds];
}
- (CGPoint) normalizedLeftEyePositionForImage:(UIImage *)image{
return [self normalizedPointForImage:image fromPoint:self.leftEyePosition];
}
- (CGPoint) normalizedRightEyePositionForImage:(UIImage *)image{
return [self normalizedPointForImage:image fromPoint:self.rightEyePosition];
}
- (CGPoint) normalizedMouthPositionForImage:(UIImage *)image{
return [self normalizedPointForImage:image fromPoint:self.mouthPosition];
}
- (CGRect) normalizedBoundsForImage:(UIImage *)image{
return [self normalizedBoundsForImage:image fromBounds:self.bounds];
}
- (CGPoint) leftEyePositionForImage:(UIImage *)image inView:(CGSize)viewSize{
CGPoint normalizedPoint = [self normalizedLeftEyePositionForImage:image];
return [self pointInView:viewSize fromNormalizedPoint:normalizedPoint];
}
- (CGPoint) rightEyePositionForImage:(UIImage *)image inView:(CGSize)viewSize{
CGPoint normalizedPoint = [self normalizedRightEyePositionForImage:image];
return [self pointInView:viewSize fromNormalizedPoint:normalizedPoint];
}
- (CGPoint) mouthPositionForImage:(UIImage *)image inView:(CGSize)viewSize{
CGPoint normalizedPoint = [self normalizedMouthPositionForImage:image];
return [self pointInView:viewSize fromNormalizedPoint:normalizedPoint];
}
- (CGRect) boundsForImage:(UIImage *)image inView:(CGSize)viewSize{
CGRect normalizedBounds = [self normalizedBoundsForImage:image fromBounds:self.bounds];
return [self boundsInView:viewSize fromNormalizedBounds:normalizedBounds];
}
- (CGPoint) pointForImage:(UIImage*) image fromPoint:(CGPoint) originalPoint {
CGFloat imageWidth = image.size.width;
CGFloat imageHeight = image.size.height;
CGPoint convertedPoint;
switch (image.imageOrientation) {
case UIImageOrientationUp:
convertedPoint.x = originalPoint.x;
convertedPoint.y = imageHeight - originalPoint.y;
break;
case UIImageOrientationDown:
convertedPoint.x = imageWidth - originalPoint.x;
convertedPoint.y = originalPoint.y;
break;
case UIImageOrientationLeft:
convertedPoint.x = imageWidth - originalPoint.y;
convertedPoint.y = imageHeight - originalPoint.x;
break;
case UIImageOrientationRight:
convertedPoint.x = originalPoint.y;
convertedPoint.y = originalPoint.x;
break;
case UIImageOrientationUpMirrored:
convertedPoint.x = imageWidth - originalPoint.x;
convertedPoint.y = imageHeight - originalPoint.y;
break;
case UIImageOrientationDownMirrored:
convertedPoint.x = originalPoint.x;
convertedPoint.y = originalPoint.y;
break;
case UIImageOrientationLeftMirrored:
convertedPoint.x = imageWidth - originalPoint.y;
convertedPoint.y = originalPoint.x;
break;
case UIImageOrientationRightMirrored:
convertedPoint.x = originalPoint.y;
convertedPoint.y = imageHeight - originalPoint.x;
break;
default:
break;
}
return convertedPoint;
}
- (CGPoint) normalizedPointForImage:(UIImage*) image fromPoint:(CGPoint) originalPoint {
CGPoint normalizedPoint = [self pointForImage:image fromPoint:originalPoint];
normalizedPoint.x /= image.size.width;
normalizedPoint.y /= image.size.height;
return normalizedPoint;
}
- (CGPoint) pointInView:(CGSize) viewSize fromNormalizedPoint:(CGPoint) normalizedPoint{
return CGPointMake(normalizedPoint.x * viewSize.width, normalizedPoint.y * viewSize.height);
}
- (CGSize) sizeForImage:(UIImage *) image fromSize:(CGSize) originalSize{
CGSize convertedSize;
switch (image.imageOrientation) {
case UIImageOrientationUp:
case UIImageOrientationDown:
case UIImageOrientationUpMirrored:
case UIImageOrientationDownMirrored:
convertedSize.width = originalSize.width;
convertedSize.height = originalSize.height;
break;
case UIImageOrientationLeft:
case UIImageOrientationRight:
case UIImageOrientationLeftMirrored:
case UIImageOrientationRightMirrored:
convertedSize.width = originalSize.height;
convertedSize.height = originalSize.width;
break;
default:
break;
}
return convertedSize;
}
- (CGSize) normalizedSizeForImage:(UIImage *) image fromSize:(CGSize) originalSize{
CGSize normalizedSize = [self sizeForImage:image fromSize:originalSize];
normalizedSize.width /= image.size.width;
normalizedSize.height /= image.size.height;
return normalizedSize;
}
- (CGSize) sizeInView:(CGSize) viewSize fromNormalizedSize:(CGSize) normalizedSize{
return CGSizeMake(normalizedSize.width * viewSize.width, normalizedSize.height * viewSize.height);
}
- (CGRect) boundsForImage:(UIImage *) image fromBounds:(CGRect) originalBounds{
CGPoint convertedOrigin = [self pointForImage:image fromPoint:originalBounds.origin];;
CGSize convertedSize = [self sizeForImage:image fromSize:originalBounds.size];
switch (image.imageOrientation) {
case UIImageOrientationUp:
convertedOrigin.y -= convertedSize.height;
break;
case UIImageOrientationDown:
convertedOrigin.x -= convertedSize.width;
break;
case UIImageOrientationLeft:
convertedOrigin.x -= convertedSize.width;
convertedOrigin.y -= convertedSize.height;
case UIImageOrientationRight:
break;
case UIImageOrientationUpMirrored:
convertedOrigin.y -= convertedSize.height;
convertedOrigin.x -= convertedSize.width;
break;
case UIImageOrientationDownMirrored:
break;
case UIImageOrientationLeftMirrored:
convertedOrigin.x -= convertedSize.width;
convertedOrigin.y += convertedSize.height;
case UIImageOrientationRightMirrored:
convertedOrigin.y -= convertedSize.height;
break;
default:
break;
}
return CGRectMake(convertedOrigin.x, convertedOrigin.y,
convertedSize.width, convertedSize.height);
}
- (CGRect) normalizedBoundsForImage:(UIImage *) image fromBounds:(CGRect) originalBounds{
CGRect normalizedBounds = [self boundsForImage:image fromBounds:originalBounds];
normalizedBounds.origin.x /= image.size.width;
normalizedBounds.origin.y /= image.size.height;
normalizedBounds.size.width /= image.size.width;
normalizedBounds.size.height /= image.size.height;
return normalizedBounds;
}
- (CGRect) boundsInView:(CGSize) viewSize fromNormalizedBounds:(CGRect) normalizedBounds{
return CGRectMake(normalizedBounds.origin.x * viewSize.width,
normalizedBounds.origin.y * viewSize.height,
normalizedBounds.size.width * viewSize.width,
normalizedBounds.size.height * viewSize.height);
}
@end
@sbauch
Copy link

sbauch commented Apr 10, 2015

You posted this solution to a lot of SO answers, but I'm having trouble getting it to work on ios8 with an image that is in UIViewContentModeScaleAspectFit. Can you confirm that this works for you on retina devices in ios 8?

@b-ray
Copy link

b-ray commented Nov 20, 2015

This is working very well, thank you!
I'd like to use this in a commercial project, is this available under the MIT license or similar?

@caevan
Copy link

caevan commented May 3, 2018

I had a couple of issues with this code. If UIImage scale != 1 then the positioning is incorrect, the fix was to multiply the image height and width by the image scale.
BoundsInView takes into account the viewSize, not the image size and position in the view, the issue becomes apparent when displaying a landscape image . I created a version of boundsInView that takes a CGRect as a parameter instead of CGSize then past it the output of AVMakeRect passing it the image size and the imageView bounds.
I have translated the code to Swift 4

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment