I need to merge UITextView and UIImageView to one UIImage.
I try to convert UITextView (background color is clear) to UIImage but the background turn to black after this code.
#define IS_OS_7_OR_LATER ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0)
-(UIImage*)imageFromView:(UIView*)view
{
CGFloat scale = [UIScreen mainScreen].scale;
UIImage *image;
if (IS_OS_7_OR_LATER)
{
//Optimized/fast method for rendering a UIView as image on iOS 7 and later versions.
UIGraphicsBeginImageContextWithOptions(view.bounds.size, YES, scale);
[view drawViewHierarchyInRect:view.bounds afterScreenUpdates:YES];
image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
}
else
{
//For devices running on earlier iOS versions.
UIGraphicsBeginImageContextWithOptions(view.bounds.size,YES, scale);
[view.layer renderInContext:UIGraphicsGetCurrentContext()];
image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
}
return image;
}
-(UIImage*)imageFromView:(UIView*)view
{
CGFloat scale = [UIScreen mainScreen].scale;
UIImage *image;
UIGraphicsBeginImageContextWithOptions(view.bounds.size, NO, scale);
if ([view respondsToSelector:#selector(drawViewHierarchyInRect:afterScreenUpdates:)]) {
[view drawViewHierarchyInRect:view.bounds afterScreenUpdates:YES];
}else{
[view.layer renderInContext:UIGraphicsGetCurrentContext()];
}
image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}
If you can change your method to the code above
(please note the correct way to change method according to OS - if class responds to that method check) -
The opaque boolean should be NO, where your code was asking the view to be opaque. Changing it to say NO should make it clear and solve your issue. I haven't had chance to test this code, though it should work. If not then at the very least the OS checking is better this way.
I hope this help
Thanks
Related
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]; }
I want to take my NSView(With layers) as an image can I do so in OSX ?
in iOS I would do the following
-(UIImage*) makeImage//snapshot the view
{
UIGraphicsBeginImageContext(self.view.bounds.size);
[self.view.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return viewImage;
}
I tried this solution from 1 of the SO answers
[[NSImage alloc] initWithData:[view dataWithPDFInsideRect:[view bounds]]];
but it didn't work because I have layers in my NSView.
I started from converting UI to NS
and now I have warnings on every line :)
-(NSImage*) makeImage :(RMBlurredView*)view
{
UIGraphicsBeginImageContext(view.bounds.size);
[self.view.layer renderInContext:UIGraphicsGetCurrentContext()];
NSImage *viewImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return viewImage;
}
I am not familiar with OSX can some 1 help me to convert this code to OSX ?
drawing to the image is tad different than in iOS:
you create a blank image, LOCK on to it, so all drawing goes to that graphics context
NSImage *image = [[NSImage alloc] initWithSize:self.view.bounds.size];
[image lockFocus];
you draw your layer same as on iOS
CGContextRef ctx = [NSGraphicsContext currentContext].graphicsPort;
[self.view.layer renderInContext:ctx];
unlock image
[image unlockFocus];
NOTE this is only if your view is layered. it doesn't work for non-layered views!
your view -as shown above- is layer backed so all's fine ;)
I'm attempting to save the contents of a UIView (and it's subviews) into a UIImage.
Here is the code I am using:
+(UIImage *)imageWithView:(UIView *)view {
UIGraphicsBeginImageContextWithOptions([view bounds].size, YES, 0);
[[view layer] renderInContext:UIGraphicsGetCurrentContext()];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}
It works great... the first time. However, if I then modify subviews of the view and call this method again, I get the old UIImage every time.
It's my understanding that UIGraphicsEndImageContext() does in fact pop the bitmap image off of the stack.
How can I make this imageWithView: method work, taking into account the current state of the view's subviews?
I hope this helps:
UIGraphicsBeginImageContext(self.view.frame.size);
[testView.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
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];
On iphone, is it possible to "screen capture" an UIView and all its subview? If it is possible, how?
I found this, but I haven't tried it myself.
Here you find the used -renderInContext.
I transformed the code above to a category on UIView.
call it like this: [aView saveScreenshotToPhotosAlbum];
#import <QuartzCore/QuartzCore.h>
- (UIImage*)captureView {
CGRect rect = [[UIScreen mainScreen] bounds];
UIGraphicsBeginImageContext(rect.size);
CGContextRef context = UIGraphicsGetCurrentContext();
[self.layer renderInContext:context];
UIImage *img = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return img;
}
- (void)saveScreenshotToPhotosAlbum {
UIImageWriteToSavedPhotosAlbum([self captureView], nil, nil, nil);
}