I'm trying to figure out if there is any way to mirror an image. For example, take a picture of someone's face and then cut it in half and show what their face looks like with each side mirrored. There doesn't seem to be any tricks like this in CGAffineTransform functions. Graphics experts please help!!!
6 Answers
The basic "trick" here is to use a scaling transform about the X or Y axis with a factor of -1. For example, you could use this to create a "flip about the horizontal axis" transform:
CGAffineTransform transform = CGAffineTransformScale(transform, -1, 1);
Then you can set the transform
property on a UIImageView
to flip the assigned image, or concatenate it with another transform to do more sophisticated effects. To get the exact effect you described, you may need to write some custom drawing code to draw your original image into a context, then overlay the flipped half on top of it. This is relatively straightforward in Core Graphics.
-
6or use CGAffineTransformMakeScale i.e. picker.cameraViewTransform = CGAffineTransformMakeScale(-1, 1) //swift – khunshan Dec 26 '14 at 07:10
-
1Excellent! I used `myImageView.transform = CGAffineTransformMakeScale(-1, 1);` – chris P Jul 06 '15 at 16:09
If you only plan on supporting 4.0+
UIImageOrientation flippedOrientation = UIImageOrientationUpMirrored;
switch (image.imageOrientation) {
case UIImageOrientationUp: break;
case UIImageOrientationDown: flippedOrientation = UIImageOrientationDownMirrored; break;
// ...
}
UIImage * flippedImage = [UIImage imageWithCGImage:image.CGImage scale:image.scale orientation:flippedOrientation];

- 33,468
- 5
- 78
- 96
You may think, why bother with the outrageously long switch statement?
? UIImage *flip = [UIImage imageWithCGImage:image.CGImage
? scale:image.scale
? orientation:(image.imageOrientation + 4) % 8];
And if you take a look at the enum you can see that modular arithmetic would do:
typedef NS_ENUM(NSInteger, UIImageOrientation) {
UIImageOrientationUp, // default orientation
UIImageOrientationDown, // 180 deg rotation
UIImageOrientationLeft, // 90 deg CCW
UIImageOrientationRight, // 90 deg CW
UIImageOrientationUpMirrored, // as above but image mirrored along other axis. horizontal flip
UIImageOrientationDownMirrored, // horizontal flip
UIImageOrientationLeftMirrored, // vertical flip
UIImageOrientationRightMirrored, // vertical flip
};
But this code is too clever. You should write a function with an explicit switch statement instead. E.g.
UIImageOrientation mirroredImageOrientation(UIImageOrientation orientation) {
switch(orientation) {
case UIImageOrientationUp: return UIImageOrientationUpMirrored;
case UIImageOrientationDown: return UIImageOrientationDownMirrored;
case UIImageOrientationLeft: return UIImageOrientationLeftMirrored;
case UIImageOrientationRight: return UIImageOrientationRightMirrored;
case UIImageOrientationUpMirrored: return UIImageOrientationUp;
case UIImageOrientationDownMirrored: return UIImageOrientationDown;
case UIImageOrientationLeftMirrored: return UIImageOrientationLeft;
case UIImageOrientationRightMirrored: return UIImageOrientationRight;
default: return orientation;
}
}
And use the function like this:
UIImage *flip = [UIImage imageWithCGImage:image.CGImage
scale:image.scale
orientation:mirroredImageOrientation(image.imageOrientation)];
I've added question marks to indicate questionable, smelly code. Similar to The Practice of Programming

- 1,296
- 12
- 17
-
1Actually if your answer seems good, it isn't in every case. e.g. if you want to do horizontal flip but your image orientation is Right, you have to do LeftMirrored, cause RightMirrored will give vertical flip. – Tancrede Chazallet Aug 01 '14 at 16:06
-
Going from non-mirrored to mirrored will horizontally mirror the image, from the perspective of you sitting down at your seat. (You're right that from the perspective of the image itself it will flip according to annotations in the enum.) If the faces are oriented in the proper direction (top of head to top of image) then all transformations from non-mirrored to mirrored will flip that face horizontally (i.e. along a vertical axis). Documentation for UIImageOrientation: https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIImage_Class/#//apple_ref/c/tdef/UIImageOrientation. – sabalaba Dec 15 '15 at 19:51
-
I edited my answer to suggest using an explicit switch statement. Who knows what will happen down the road. Maybe Apple will change the ordering of the enum in which case the modular arithmetic version becomes incorrect. – sabalaba Dec 15 '15 at 20:11
None of the answers above, respond to the part of question that is mirroring half of the image not flipping the whole image. Mixing the solutions leads to the following sample function you may use as a category such as UIImage+Mirroring :
(UIImage *) horizontalMirror {
UIImageOrientation flippedOrientation = UIImageOrientationUpMirrored;
switch (self.imageOrientation) {
case UIImageOrientationUp: break;
case UIImageOrientationDown: flippedOrientation = UIImageOrientationDownMirrored; break;
}
UIImage * flippedImage = [UIImage imageWithCGImage:self.CGImage scale:1.0 orientation:flippedOrientation];
CGImageRef inImage = self.CGImage;
CGContextRef ctx = CGBitmapContextCreate(NULL,
CGImageGetWidth(inImage),
CGImageGetHeight(inImage),
CGImageGetBitsPerComponent(inImage),
CGImageGetBytesPerRow(inImage),
CGImageGetColorSpace(inImage),
CGImageGetBitmapInfo(inImage)
);
CGRect cropRect = CGRectMake(flippedImage.size.width/2, 0, flippedImage.size.width/2, flippedImage.size.height);
CGImageRef TheOtherHalf = CGImageCreateWithImageInRect(flippedImage.CGImage, cropRect);
CGContextDrawImage(ctx, CGRectMake(0, 0, CGImageGetWidth(inImage), CGImageGetHeight(inImage)), inImage);
CGAffineTransform transform = CGAffineTransformMakeTranslation(flippedImage.size.width, 0.0);
transform = CGAffineTransformScale(transform, -1.0, 1.0);
CGContextConcatCTM(ctx, transform);
CGContextDrawImage(ctx, cropRect, TheOtherHalf);
CGImageRef imageRef = CGBitmapContextCreateImage(ctx);
CGContextRelease(ctx);
UIImage *finalImage = [UIImage imageWithCGImage:imageRef];
CGImageRelease(imageRef);
return finalImage;
}

- 5,279
- 2
- 43
- 78

- 2,726
- 3
- 22
- 24
It's easier to just use:
UIImage(assetIdentifier: .myIcon)?.withHorizontallyFlippedOrientation()

- 6,684
- 2
- 34
- 65
You can use below code for Swift 4.0
func didTakePicture(_ real_image: UIImage) {
//suppose real_image = :)
var flipped_image = UIImage(CGImage: real_image.CGImage!, scale: real_image.scale, orientation: .leftMirrored)
// flipped_image is (:
}

- 812
- 9
- 18