Capture UIView as UIImage - objective-c

I have been using this method to convert a UIView into UIImage. i.e. screen snapshot of a view -
#interface UIView(Extended)
- (UIImage *) imageByRenderingView;
#end
#implementation UIView(Extended)
- (UIImage *)imageByRenderingView
{
UIGraphicsBeginImageContext(self.bounds.size);
[self.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *resultingImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return resultingImage;
}
#end
To use it, I do this -
UIImage *currImage = [self.view imageByRenderingView];
This gives the image representation of the entire UIView. Now I want 2 images, one is of the top half of the UIView and the other is the bottom half. How do I do that?

You can split your UIImage in two by using this code:
CGImageRef topOfImageCG =
CGImageCreateWithImageInRect(currImage.CGImage,
CGRectMake(0,
0,
currImage.size.width,
currImage.size.height / 2.0));
UIImage *topOfImage = [UIImage imageWithCGImage:topOfImageCG];
CGImageRelease(topOfImageCG);

Related

How to take ScreenShot Of UIView Which is not in memory iOS

I want to convert UIView to UIImage, in which the view is in background and when I checked view hierarchy, it is there as white space, probably it wont get loaded..
What I wanted to do is load the view into memory and convert into image.
you just need to initialize your view with your required frame and then pass to below code as targetView. Initialize your view before you call screen capture method like below
UIView *targetView = [[UIView alloc]initWithFrame:CGRectMake(0, 0, 320, 568)]; //Initilization
UIImage *capturedImage = [self captureScreen:targetView]; //Call method
- (UIImage *)captureScreen:(UIView*)targetView
{
UIView* captureView = targetView;
UIGraphicsBeginImageContextWithOptions(captureView.bounds.size, captureView.opaque, 0.0);
[captureView.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage * screenshot = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
CGRect cropRect = CGRectMake(0 ,0 ,captureView.frame.size.width ,captureView.frame.size.height);
UIGraphicsBeginImageContextWithOptions(cropRect.size, captureView.opaque, 1.2f);
[screenshot drawInRect:cropRect];
UIImage * customScreenShot = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return customScreenShot;
}
Use this:
- (UIImage*)snapShot:(UIView*)myView {
UIGraphicsBeginImageContext(myView.frame.size);
[myView.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return viewImage;
}

Flipping image not working on iOS 10

I am facing weird issue while flipping Image in iOS 10
Here is my code.
uiImage = [[UIImage alloc] initWithCIImage:ciImage];
flippedImg = [UIImage imageWithCIImage:ciImage scale:uiImage.scale orientation:UIImageOrientationDownMirrored];
captureImgView.image = flippedImg;
I am taking one ciImage and getting it into uiImage.
then flipping that UIImage.
this code works fine on all iOS version, lower than 10.
but not working on 10 and above.
I tried all Orientations,
UIImageOrientationUpMirrored
UIImageOrientationLeftMirrored
UIImageOrientationUp
UIImageOrientationRight
UIImageOrientationDown
UIImageOrientationLeft
UIImageOrientationDownMirrored
UIImageOrientationRightMirrored
But nothing work.
I am taking selfie from front camera and attaching that selfie to UIImageView.
I don't want to attach flipped image taken from front camera.
I want orignal image here.
Please guide me for same.
Thanks in advance.
I got the solution by my own.
What I did,
I checked for iOS10 version of system,
captured the image from front camera, converted from CIImage to UIImage and placed it on the UIImageView.
Once I placed it on UIImageView,
I rotate the UIImageView using CGAffineTransformMakeRotation to fit in appropriate position and place.
here is the sample code.
NSString *systemVersion = [UIDevice currentDevice].systemVersion;
captureImgView = [[UIImageView alloc]init];
if([systemVersion floatValue] < 10.0)
{
uiImage = [[UIImage alloc] initWithCIImage:ciImage];
flippedImg = [UIImage imageWithCIImage:ciImage scale:uiImage.scale orientation:UIImageOrientationDownMirrored];
captureImgView.image = flippedImg;
captureImgView.transform = CGAffineTransformMakeRotation(M_PI_2);
}
else
{
uiImage = [[UIImage alloc] initWithCIImage:ciImage];
flippedImg = [UIImage imageWithCIImage:ciImage scale:uiImage.scale orientation:UIImageOrientationUpMirrored];
captureImgView.image = uiImage;
captureImgView.transform = CGAffineTransformMakeRotation ((M_PI * 270 / 180.0));
}
I think you missed something. In my code it's working fine...
#interface ViewController ()
#property (weak, nonatomic) IBOutlet UIImageView *imgOriginal;
#property (weak, nonatomic) IBOutlet UIImageView *imgFlipped;
#end
#pragma mark - UIImagePicker delegate
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
UIImage *uiImage = info[UIImagePickerControllerOriginalImage];
CGImageRef cgImage = uiImage.CGImage;
CIImage *ciImage = [CIImage imageWithCGImage:cgImage];
UIImage *flippedImg = [UIImage imageWithCIImage:ciImage scale:uiImage.scale orientation:UIImageOrientationRight];
_imgOriginal.image = uiImage;
_imgFlipped.image = flippedImg;
[self dismissViewControllerAnimated:YES completion:nil];
}
Here output :
In iOS 10, it will be like :
#pragma mark - UIImagePicker delegate
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
UIImage *uiImage = info[UIImagePickerControllerOriginalImage];
CGImageRef cgImage = uiImage.CGImage;
//CIImage *ciImage = [CIImage imageWithCGImage:cgImage];
//UIImage *flippedImg = [UIImage imageWithCIImage:ciImage scale:uiImage.scale orientation:UIImageOrientationRight];
UIImage *flippedImg = [UIImage imageWithCGImage:cgImage scale:uiImage.scale orientation:UIImageOrientationLeftMirrored];
_imgOriginal.image = uiImage;
_imgFlipped.image = flippedImg;
[self dismissViewControllerAnimated:YES completion:nil];
}

How To Speed Up Image Blur?

I have the following code in my viewWillAppear in a modal uiviewcontroller.
I am including UIImage+ImageEffects.h to do the blurring of the background image in this example.
-(void) viewWillAppear:(BOOL)animated
{
[super viewWillAppear:NO];
// grab an image of our parent view
UIView *parentView = self.presentingViewController.view;
UIImage *parentViewImage = [self takeSnapshotOfView:parentView];
UIImage *blurredImage = nil;
//BLUR THE IMAGE
blurredImage = [self blurWithImageEffects:parentViewImage];
// insert an image view with a picture of the parent view at the back of our view's subview stack...
UIImageView *imageView = [[UIImageView alloc] initWithFrame:self.view.bounds];
imageView.image = blurredImage;
[self.view insertSubview:imageView atIndex:0];
}
[EDIT] Adding Blur Methods
- (UIImage *)takeSnapshotOfView:(UIView *)view
{
CGFloat reductionFactor = 1.5;
UIGraphicsBeginImageContext(CGSizeMake(view.frame.size.width/reductionFactor, view.frame.size.height/reductionFactor));
[view drawViewHierarchyInRect:CGRectMake(0, 0, view.frame.size.width/reductionFactor, view.frame.size.height/reductionFactor) afterScreenUpdates:YES];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}
- (UIImage *)blurWithImageEffects:(UIImage *)image
{
return [image applyBlurWithRadius:10 tintColor:[UIColor colorWithWhite:1 alpha:0.2] saturationDeltaFactor:1.5 maskImage:nil];
}
The code works fine and the background shows up blurry but it is really noticeably slow on iPad 3 with iOS 8. When the button to display this viewcontroller is tapped there is a pause before the viewcontroller slides up from the bottom. If I remove the blur the view controller slides up faster.
I tried putting the code in the viewDidAppear but then there is a noticeable white background displayed for a few seconds before the blur appears. But when in viewDidAppear the viewcontroller slides up immediately.
If I reduce the applyWithBlurRadius value this does not seem to reduce the time it takes to apply the blur.
Is there any way I can make it run faster?
GPUImage might solve your issue, Its fast and it doesn't put too much load on processing.
Link To Framework : https://github.com/BradLarson/GPUImage
Link to use GPUImage Blur
http://blog.bubbly.net/tag/gpu-image/
http://www.raywenderlich.com/60968/ios-7-blur-effects-gpuimage
However a reference is shown below which will give you the basic idea:
First prepare your view which is to blurred:
- (NSData *)PhotoForBlurring:(UIView *)view{
UIGraphicsBeginImageContextWithOptions(view.bounds.size, NO, 1.0);
[view.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
NSData * data = UIImagePNGRepresentation(image);
[data writeToFile:#"aName.png" atomically:YES];
return data; }
-(void)sharingScrapPage{
GPUImageiOSBlurFilter *blur = [[GPUImageiOSBlurFilter alloc]init];
blur.blurRadiusInPixels=2.0;
blur.downsampling=6.0;
[blurview removeFromSuperview];
blurview = [[UIImageView alloc]initWithFrame:getRectDisplay(0, 0, 480, 320)]; // Landscape Iphone 4S
UIImage *imageForBlurring=[UIImage imageWithData:[self PhotoForBlurring:self.view]];
NSData* pngdataForBlurring = UIImagePNGRepresentation (imageForBlurring);
UIImage* blurImage = [UIImage imageWithData:pngdataForBlurring];
blurImage=[blur imageByFilteringImage:blurImage];
blurview.image=blurImage;
[self.view addSubview:blurview];
[progressHUD removeFromSuperview];
progressHUD = [[ProgressHUD alloc]initWithFrame:getRectDisplay(190, 110, 100, 90)];
[blurview addSubview:progressHUD]; }

draw one image above another code not working

I have 2 images of same size and I need to make 3d picture in which 2nd is above 1st
I have UIImage class extension with following method
+(UIImage*)imageFrom2Images:(UIImage *)img1 with:(UIImage *)img2 {
UIGraphicsBeginImageContext(img1.size);
CGContextRef context = UIGraphicsGetCurrentContext();
UIGraphicsPushContext(context);
[img1 drawAtPoint:CGPointMake(0, 0)];
[img2 drawAtPoint:CGPointMake(0, 0)];
UIImage *resultingImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsPopContext();
UIGraphicsEndImageContext();
return resultingImage;
}
I've tried to save resulting image in Photo Album but it calls error and not working..It seems that this method is wrong.
UIImage*t1=[self.mw.imageFIFO lastObject];
UIImage* test=[UIImage imageFrom2Images:self.imageView.image with:t1];
UIImageWriteToSavedPhotosAlbum(test, self,
#selector(image:didFinishSavingWithError:contextInfo:), nil);
The error message I am getting is:
Error Domain=ALAssetsLibraryErrorDomain Code=-3304 "Failed to encode image for saved photos."
UserInfo=0x9398960 {NSUnderlyingError=0x935e760 "Failed to encode image for saved photos.",
NSLocalizedDescription=Failed to encode image for saved photos.}
You should never need to get the current graphics context and then push it - you're just duplicating the top of the context stack. It would be nice if it still worked, but it doesn't. Remove the calls to UIGraphicsPushContext and UIGraphicsPopContext, and it works as intended.
+(UIImage*)imageFrom2Images:(UIImage *)img1 with:(UIImage *)img2 {
UIGraphicsBeginImageContext(img1.size);
[img1 drawAtPoint:CGPointMake(0, 0)];
[img2 drawAtPoint:CGPointMake(0, 0)];
UIImage *resultingImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return resultingImage;
}
To detect these problems in future, check the output from imageFrom2Images. As originally implemented, it returned nil, so it's not surprising that the following calls didn't know what to do. (If it had returned an image object, the next step would be to display it inside a UIImageView, to make sure it's the correct image.)
This method should do it:
-(UIImage *)drawFirstImage:(UIImage*)firstImage afterSecondImage:(UIImage *)secondImage
{
float finalWidth=MAX(firstImage.size.width,secondImage.size.width);
float finalHeight=firstImage.size.height + secondImage.size.height;
CGSize finalSize=CGSizeMake(finalWidth, finalHeight);
UIGraphicsBeginImageContext(finalSize);
[firstImage drawInRect:CGRectMake(0, 0, firstImage.size.width, firstImage.size.height)];
[secondImage drawInRect:CGRectMake(0, firstImage.size.height, secondImage.size.width, secondImage.size.height)];
UIImage *resultImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return resultImage;
}
You can use it as:
UIImage *resultImage= [self drawFirstImage:image1 afterSecondImage:image2];
Here it is a category implementation:
UIImage+MyExtensions.h
#import <UIKit/UIKit.h>
#interface UIImage (MyExtensions)
-(UIImage *)attachImageBelow:(UIImage *)secondImage;
#end
UIImage+MyExtensions.m
#import "UIImage+MyExtensions.h"
#implementation UIImage (MyExtensions)
-(UIImage *)attachImageBelow:(UIImage *)secondImage{
float finalWidth=MAX(self.size.width,secondImage.size.width);
float finalHeight=self.size.height + secondImage.size.height;
CGSize finalSize=CGSizeMake(finalWidth, finalHeight);
UIGraphicsBeginImageContext(finalSize);
[self drawInRect:CGRectMake(0, 0, self.size.width, self.size.height)];
[secondImage drawInRect:CGRectMake(0, self.size.height, secondImage.size.width, secondImage.size.height)];
UIImage *resultImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return resultImage;
}
You can use it like this:
#import "UIImage+MyExtensions.h"
UIImage *resultImage= [image1 attachImageBelow:image2];

How to implement highlighting on UIImage like UIButton does when tapped?

I need to replicate the effect that the UIButton does on an image when tapped, the highlighting. See:
The original PNG is a square with alpha background. When I set it as UIButton's image it automatically apply an effect on the non-alpha pixels of the image.
How to do this effect?
You could achieve this with a simple category on UIImage:
#interface UIImage (Tint)
- (UIImage *)tintedImageUsingColor:(UIColor *)tintColor;
#end
#implementation UIImage (Tint)
- (UIImage *)tintedImageUsingColor:(UIColor *)tintColor {
UIGraphicsBeginImageContextWithOptions(self.size, NO, self.scale);
CGRect drawRect = CGRectMake(0, 0, self.size.width, self.size.height);
[self drawInRect:drawRect];
[tintColor set];
UIRectFillUsingBlendMode(drawRect, kCGBlendModeSourceAtop);
UIImage *tintedImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return tintedImage;
}
#end
For the effect shown above, you'd pass something like [UIColor colorWithWhite:0.0 alpha:0.3] as the tintColor parameter (experiment with the alpha value).