How can improve UISlider response for blending mode? - ios

I would use UISlider to adjust the alpha through below codes. However, the response of slider is very slow. How can I improve it?
Thank in advance.
-(IBAction)alphaSliderAction:(UISlider*)slider
{
//blending images
UIGraphicsBeginImageContextWithOptions(bgImage.size, YES, 0.0);
//
// Use existing opacity as is
[bgImage drawInRect:CGRectMake(0,0,bgImage.size.width,bgImage.size.height)];
[layerAImage drawInRect:CGRectMake(0,0,bgImage.size.width,bgImage.size.height) blendMode:kCGBlendModeOverlay alpha:slider.value];
finalImage = UIGraphicsGetImageFromCurrentImageContext();
//
UIGraphicsEndImageContext();
//
imgView.image=finalImage;
}

You could try doing the drawing using CoreImage instead of CoreGraphics. The CoreImage CIOverlayBlendMode filter does the same thing but might be faster.

Don't use drawRect at all. Instead, install your image in an image view, and set the alpha property on the image view. You'll need to set the opaque flag on the image view to NO. That will do the blending using the GPU, which should be much faster.
Alternately you could install the image's CGImage in a layer's content property and add that layer to your view. Then you could set the opacity of the layer. You could use the implicit animation on CALayers this way.

Related

How to save image with transparent stroke

I followed #Rob answer and its drawn as I want...but when I saved this image....stroke not transparent anymore
Objective-C How to avoid drawing on same color image having stroke color of UIBezierPath
For save image I written this code
-(void)saveImage {
UIGraphicsBeginImageContextWithOptions(self.upperImageView.bounds.size, NO, 0);
if ([self.upperImageView respondsToSelector:#selector(drawViewHierarchyInRect:afterScreenUpdates:)])
[self.upperImageView drawViewHierarchyInRect:self.upperImageView.bounds afterScreenUpdates:YES]; // iOS7+
else
[self.upperImageView.layer renderInContext:UIGraphicsGetCurrentContext()]; // pre iOS7
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndPDFContext();
UIImageWriteToSavedPhotosAlbum(self.upperImageView.image, self,#selector(image:didFinishSavingWithError:contextInfo:), nil);
}
You are either setting the alpha of the image view with the paths to 1.0 somewhere, or you are using something that doesn't permit transparencies (e.g. UIGraphicsBeginImageContextWithOptions with YES for the opaque parameter, or staging the image in a format that doesn't preserve alpha, such as JPEG).
A few additional thoughts:
I notice that you're only drawing upperImageView. If you want the composite image, you need to draw both. Or are you only trying to save one of the image views?
(For those unfamiliar with that other question, the entire point was how to draw multiple paths over an image, and have the full set of those paths with the same reduced alpha, rather than having the intersection of paths lead to some additive behavior. This was accomplished by having two separate image views, one for the underlying image, and one for the drawn paths. The key to the answer to that question was that one should draw the paths at 100% alpha, but to add that as a layer to a view that, itself, has a reduced alpha.)
What is the alpha of the image view upon which you are drawing.
NB: In the answer to that other question, when saving a temporary copy of the combined paths. we had to temporarily set the alpha to 1.0. But when saving the final result here, we want to keep the "path" image view's alpha at its reduced value.
Unrelated, but you faithfully transcribed a typo (since fixed) in my original example where I accidentally called UIGraphicsEndPDFContext rather than UIGraphicsEndImageContext. You should use the latter.
So, considering two image views, one with the photograph and one with the drawn path, called imageImageView (with alpha of 1.0) and pathsImageView (with alpha of 0.5), respectively, I can save the snapshot like so:
- (void)saveSnapshot {
CGRect rect = self.pathsImageView.bounds;
UIGraphicsBeginImageContextWithOptions(rect.size, NO, 0);
if ([self.pathsImageView respondsToSelector:#selector(drawViewHierarchyInRect:afterScreenUpdates:)]) {
[self.imageImageView drawViewHierarchyInRect:rect afterScreenUpdates:YES]; // iOS7+
[self.pathsImageView drawViewHierarchyInRect:rect afterScreenUpdates:YES];
} else {
[self.imageImageView.layer renderInContext:UIGraphicsGetCurrentContext()]; // pre iOS7
[self.pathsImageView.layer renderInContext:UIGraphicsGetCurrentContext()];
}
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
UIImageWriteToSavedPhotosAlbum(image, self, #selector(image:didFinishSavingWithError:contextInfo:), nil);
}
When I did that, the resulting composite image was in my photo album:

view.layer drawInContext:UIGraphicsGetCurrentContext() not drawing

I am trying to draw a UIView into a UIImage. Here is the code that I'm using:
UIGraphicsBeginImageContextWithOptions(myView.bounds.size, YES, 0.f);
[myView.layer drawInContext:UIGraphicsGetCurrentContext()];
UIImage *img = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
I've verified myView.bounds.size to be valid. myView displays correctly on screen. However, img is completely black (I've tried displaying on both in an UIImageView and tried writing the JPEG representation to file.) The image dimensions are correct, the color space (in JPEG file output) is RGB, color profile is sRGB etc. which means that we're not dealing with a corrupted image (in the sense that image/bitmap data itself is valid). I've tested the case on both 6.0 simulator, 7.0 simulator, and 7.0.6 device, all the same. The layer doesn't have any sublayers, and I've tried setting masksToBounds to NO which didn't change anything.
What could be causing the view's layer not to draw?
You need to change:
[myView.layer drawInContext:UIGraphicsGetCurrentContext()];
to:
[myView.layer renderInContext:UIGraphicsGetCurrentContext()];
Note that drawInContext: does not actually do anything by default:
The default implementation of this method does not doing any drawing
itself. If the layer’s delegate implements the drawLayer:inContext:
method, that method is called to do the actual drawing.
Subclasses can override this method and use it to draw the layer’s
content. When drawing, all coordinates should be specified in points
in the logical coordinate space.
A UIView's layer delegate is set to the UIView, but it does not look like the UIView necessarily draws to the provided context. More investigation is necessary on this point.
update: per Rob Jones' comment, not these APIs return UIViews, not images.
There is a new API in iOS 7 that looks promising:
- (UIView *)snapshotViewAfterScreenUpdates:(BOOL)afterUpdates NS_AVAILABLE_IOS(7_0);
- (UIView *)resizableSnapshotViewFromRect:(CGRect)rect afterScreenUpdates:(BOOL)afterUpdates withCapInsets:(UIEdgeInsets)capInsets NS_AVAILABLE_IOS(7_0); // Resizable snapshots will default to stretching the center
- (BOOL)drawViewHierarchyInRect:(CGRect)rect afterScreenUpdates:(BOOL)afterUpdates NS_AVAILABLE_IOS(7_0);
Check the UIView (UISnapshotting) category in UIView.h

Implement Blur over parts of view

How can I implement the image below pragmatically - meaning the digits can change at runtime or even be replaced with a movie?
Just add a blurred UIView on top of your thing.
For example...make a UIImage of your desired view size, blur it using CIFilter and then add it to your view .It should achieve the desired effect.
This is generally the same question and is answered by quite a few methods.. Anyway I would propose 1 more:
Get the image from UIView
+ (UIImage *)imageFromLayer:(CALayer *)layer {
UIGraphicsBeginImageContext([layer frame].size);
[layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *outputImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return outputImage;
}
rather yet play around a bit with this to get the desired part of the view as the image. Now create a new view and add to it image views (with the image you get from layer). Then move the centers of the image views to achieve gaussian algorithm and take the image from this layer again and place it back on the original view.
Moving the center should be defined by radius fragment (I'd start with .5f) and resample range.
for(int i=1; i<resampleCount; i++) {
view1.center = CGPointMake(view1.center.x + radiusFragment*i, view1.center.y);
view2.center = CGPointMake(view2.center.x - radiusFragment*i, view2.center.y);
view3.center = CGPointMake(view3.center.x, view3.center.y + radiusFragment*i);
view4.center = CGPointMake(view4.center.x, view4.center.y - radiusFragment*i);
//add the subviews
}
//get the image from view
All the subviews need to have alpha set to 1.0f/(resampleCount*4)
This method might not be the fastest but it would be extremely easy to implement and if you can pimp the radius and resample range to minimum fragments it should do pretty well.
use a UIView whith white background and decrease the alpha property
blurView.backgroundColor=[UIColor colorWithRed:255 green:255 blue:255 alpha:0.3]

iOS animate a blur for a view

I would like to quickly animate a blur on a UIView to use as a transition in my app. I'm having trouble knowing where to start. I believe core image is the proper tool for the job. Can anyone point me to a sample of how to blur a UIView? I'm assuming I will need to convert the view into a single UIImage, but I don't know where to proceed from there.
Thanks in advance!
Taking a snapshot of the View and using GPUImage from Brad Larson (the GPUImageGaussianBlurFilter) got me some nice results.
To animate the view I created a ImageView with the blurred image and animated the alpha channel from 0 to 1 to make the blur appear progressively.
Alternatively, I presume its possible to increase the blursize per frame.
#import "GPUImage.h"
...
[view.layer renderInContext:UIGraphicsGetCurrentContext()];
...
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
...
GPUImageGaussianBlurFilter * filter = [[GPUImageGaussianBlurFilter alloc] init];
filter.blurSize = 0.5;
UIImage * blurred = [filter imageByFilteringImage:image];
rasterizeScale of a uiview's layer is what you need, Here is the code for adding blur effect to UIVIew:
CALayer *layer = [self.blurView layer];
[layer setRasterizationScale:0.3];
[layer setShouldRasterize:YES];
For details refer to Apple Documentation of CALayer, Also this tutorial might help You, hope that helps
I recently did some tests with blurring a series of images at different blur settings and animating them simply with UIImageView. You might want to take a look:
AnimatedGaussianBlur

Use stretchable UIImage in CGContext

I'm searching a way to draw stretchable image as background of my custom cell background view. I would like to use drawRect method and draw an image stretched exactly as it would be stretched with stretchableImageWithLeftCapWidth in a UIImageView... how can i continue this code to make it happen ?
- (void)drawRect:(CGRect)rect{
CGContextRef context = UIGraphicsGetCurrentContext();
UIImage *bgImg =[[UIImage imageNamed:#"bg_table_top"]stretchableImageWithLeftCapWidth:3 topCapHeight:0];
//How to draw the image stretched as the self.bounds size ?
....
}
Any reason not to let UIImageView do this? (Include one as a child of your custom cell.) It's true that reducing child views can be a performance improvement in tables, but UIImageView is also pretty good at getting good performance when drawing images.
My guess is otherwise you're going to have to do multiple draw calls, in order to get the ends and middle drawn correctly.

Resources