Screenshot low quality iOS - ios

In my project I have to make a screenshot of the screen and apply blur to create the effect of frosted glass. Content can be moved under the glass and then method bluredImageWithRect: called. I'm trying to optimize the following method to speed up the application. Major losses occur when a blur filter is applied to the screenshot, so I'm looking for a way to take a screenshot in a lower resolution, apply a blur to the screenshot, and then stretch it to fit some rect.
- (CIImage *)bluredImageWithRect:(CGRect)rect {
CGSize smallSize = CGSizeMake(rect.size.width, rect.size.height);
CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB();
CGContextRef ctx = CGBitmapContextCreate(nil, smallSize.width, smallSize.height, 8, 0, colorSpaceRef, kCGImageAlphaPremultipliedFirst);
CGContextClearRect(ctx, rect);
CGColorSpaceRelease(colorSpaceRef);
CGContextSetInterpolationQuality(ctx, kCGInterpolationNone);
CGContextSetShouldAntialias(ctx, NO);
CGContextSetAllowsAntialiasing(ctx, NO);
CGContextTranslateCTM(ctx, 0.0, self.view.frame.size.height);
CGContextScaleCTM(ctx, 1, -1);
CGImageRef maskImage = [UIImage imageNamed:#"mask.png"].CGImage;
CGContextClipToMask(ctx, rect, maskImage);
[self.view.layer renderInContext:ctx];
CGImageRef imageRef1 = CGBitmapContextCreateImage(ctx);
CGContextRelease(ctx);
NSDictionary *options = #{(id)kCIImageColorSpace : (id)kCFNull};
CIImage *beforeFilterImage = [CIImage imageWithCGImage:imageRef1 options:options];
CGImageRelease(imageRef1);
CIFilter *blurFilter = [CIFilter filterWithName:#"CIGaussianBlur" keysAndValues:kCIInputImageKey, beforeFilterImage, #"inputRadius", [NSNumber numberWithFloat:3.0f], nil];
CIImage *afterFilterImage = blurFilter.outputImage;
CIImage *croppedImage = [afterFilterImage imageByCroppingToRect:CGRectMake(0, 0, smallSize.width, smallSize.height)];
return croppedImage;
}

Here is a tutorial iOS image processing with the accelerate framework that shows how to do a blur effect that may be fast enough for what you need.

Related

draw border around CIImage

I'm looking for a way to add a solid border with Core Image. I have implement custom camera for taking pictures of rectangle shape documents. Now I am getting that documents four coordinates but problem to draw border on CIImage. Please help me.
CIImage *overlay = [CIImage imageWithColor:[CIColor colorWithRed:0 green:1 blue:0 alpha:0.6]];
overlay = [overlay imageByCroppingToRect:image.extent];
overlay = [overlay imageByApplyingFilter:#"CIPerspectiveTransformWithExtent" withInputParameters:#{#"inputExtent":[CIVector vectorWithCGRect:image.extent],#"inputTopLeft":[CIVector vectorWithCGPoint:topLeft],#"inputTopRight":[CIVector vectorWithCGPoint:topRight],#"inputBottomLeft":[CIVector vectorWithCGPoint:bottomLeft],#"inputBottomRight":[CIVector vectorWithCGPoint:bottomRight]}];
return [overlay imageByCompositingOverImage:image];
You can use this methods :
- (UIImage *)addBorderToImage:(UIImage *)image {
CGImageRef bgimage = [image CGImage];
float width = CGImageGetWidth(bgimage);
float height = CGImageGetHeight(bgimage);
// Create a temporary texture data buffer
void *data = malloc(width * height * 4);
// Draw image to buffer
CGContextRef ctx = CGBitmapContextCreate(data,
width,
height,
8,
width * 4,
CGImageGetColorSpace(image.CGImage),
kCGImageAlphaPremultipliedLast);
CGContextDrawImage(ctx, CGRectMake(0, 0, (CGFloat)width, (CGFloat)height), bgimage);
//Set the stroke (pen) color
CGContextSetStrokeColorWithColor(ctx, [UIColor greenColor].CGColor);
//Set the width of the pen mark
CGFloat borderWidth = (float)width*0.05;
CGContextSetLineWidth(ctx, borderWidth);
//Start at 0,0 and draw a square
CGContextMoveToPoint(ctx, 0.0, 0.0);
CGContextAddLineToPoint(ctx, 0.0, height);
CGContextAddLineToPoint(ctx, width, height);
CGContextAddLineToPoint(ctx, width, 0.0);
CGContextAddLineToPoint(ctx, 0.0, 0.0);
//Draw it
CGContextStrokePath(ctx);
// write it to a new image
CGImageRef cgimage = CGBitmapContextCreateImage(ctx);
UIImage *newImage = [UIImage imageWithCGImage:cgimage];
CFRelease(cgimage);
CGContextRelease(ctx);
// auto-released
return newImage;
}
Calling this method:
UIImage *updatedIMG = [self addBorderToImage:[[UIImage alloc] initWithCIImage:overlay]]

Black and White Photoshop effect on UIImage

Hello I'd like to create the following Black and White Photoshop effect on a UIImage
https://drive.google.com/file/d/0B5dHxpdDwpPec3dPTWdLVnNhZFk/view?usp=sharing
In which you can change the brightness of each of the six colors (reds yellows green cyans blues magentas)
I used this to make the image black and white but it doesn't allow me to change the specific colors
self.imageView.image = chosenImage;
CIImage *beginImage = [CIImage imageWithCGImage:chosenImage.CGImage];
CIImage *blackAndWhite = [CIFilter filterWithName:#"CIColorControls" keysAndValues:kCIInputImageKey, beginImage, #"inputBrightness", [NSNumber numberWithFloat:0.0], #"inputContrast", [NSNumber numberWithFloat:1.1], #"inputSaturation", [NSNumber numberWithFloat:0.0], nil].outputImage;
CIImage *output = [CIFilter filterWithName:#"CIExposureAdjust" keysAndValues:kCIInputImageKey, blackAndWhite, #"inputEV", [NSNumber numberWithFloat:0.7], nil].outputImage;
CIContext *context = [CIContext contextWithOptions:nil];
CGImageRef cgiimage = [context createCGImage:output fromRect:output.extent];
UIImage *newImage = [UIImage imageWithCGImage:cgiimage];
self.imageView.image = newImage;
Thank You for your time
I think you can accomplish that effect with the following function:
- (UIImage *)grayScaleImageWith:(UIImage *)image blackPoint:(CGFloat)blackPoint whitePoint:(CGFloat)whitePoint andGamma:(CGFloat)gamma {
// Create image rectangle with current image width/height
CGRect imageRect = CGRectMake(0, 0, image.size.width, image.size.height);
// Grayscale color space
CGColorSpaceRef colorSpace = CGColorSpaceCreateCalibratedGray(whitePoint, blackPoint, gamma);
// Create bitmap content with current image size and grayscale colorspace
CGContextRef context = CGBitmapContextCreate(nil, image.size.width, image.size.height, 8, 0, colorSpace, kCGImageAlphaNone);
// Draw image into current context, with specified rectangle
// using previously defined context (with grayscale colorspace)
CGContextDrawImage(context, imageRect, [image CGImage]);
// Create bitmap image info from pixel data in current context
CGImageRef imageRef = CGBitmapContextCreateImage(context);
// Create a new UIImage object
UIImage *newImage = [UIImage imageWithCGImage:imageRef];
// Release colorspace, context and bitmap information
CGColorSpaceRelease(colorSpace);
CGContextRelease(context);
CFRelease(imageRef);
// Return the new grayscale image
return newImage;
}
Then call it filling the black and white values with the values selected on the UI:
CGFloat black[3] = { 0, 0, 0 }; // replace content with values from interface
CGFloat white[3] = { 100, 100, 100 }; // replace content with values from interface
[self grayScaleImageWith:image blackPoint:black whitePoint:white andGamma:1.8f];
I have not tested this code yet but I hope at least it points you in the right direction.

Masking a transparent image with another actual image in iOS

I have two images, one is a mask that is transparent with some edges / borders and the other is the actual image. I want to merge both of them.
I have used the following code to mask and combine the image:
- (UIImage*) maskImage:(UIImage *)image withMask:(UIImage *)maskImage {
// create a bitmap graphics context the size of the image
CGFloat dim = MIN(image.size.width, image.size.height);
CGSize size = CGSizeMake(dim, dim);
UIGraphicsBeginImageContextWithOptions(size, NO, .0);
UIBezierPath *bezierPath = [UIBezierPath bezierPathWithOvalInRect:(CGRect){ CGPointZero, size }];
[bezierPath fill];
[bezierPath addClip];
CGPoint offset = CGPointMake((dim - image.size.width) * 0.5, (dim - image.size.height) * 0.5);
[image drawInRect:(CGRect){ offset, image.size }];
UIImage *ret = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return ret;
}
The result:
In the result image, the border of the image used as a mask is missing. Can someone please help me with this?
I wrote a masking category for ios (well it is basically cross platform because CoreImage is on both platforms anyway:
github project
the core functionality boils down to this (for your example)
UIImage *person = ...
UIImage *circle = ...
UIImage *result = [person imageMaskedWith:circle];
UIImageView *redbox = [[UIImageView alloc] initWithImage:result];
redbox.backgroundColor = [UIColor redColor]; //this can be a gradient!
the main part of the code from the category:
CGImageRef imageReference = image.CGImage;
CGImageRef maskReference = mask.CGImage;
CGRect rect = CGRectMake(0, 0, CGImageGetWidth(imageReference), CGImageGetHeight(imageReference));
// draw with Core Graphics
UIGraphicsBeginImageContext(rect.size);
CGContextRef bitmap = UIGraphicsGetCurrentContext();
CGContextTranslateCTM(bitmap, 0.0, rect.size.height);
CGContextScaleCTM(bitmap, 1.0, -1.0);
CGContextClipToMask(bitmap, rect, maskReference);
CGContextDrawImage(bitmap, rect, imageReference);
newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

changing the color of image in iphone sdk

I have a image & i want to change the color of that image through programatically.
& I want to change the color of this image
UPDATE:
Use this method...
-(UIImage *)imageNamed:(NSString *)name withColor:(UIColor *)color {
// load the image
UIImage *img = [UIImage imageNamed:name];
// begin a new image context, to draw our colored image onto
UIGraphicsBeginImageContext(img.size);
// get a reference to that context we created
CGContextRef context = UIGraphicsGetCurrentContext();
// set the fill color
[color setFill];
// translate/flip the graphics context (for transforming from CG* coords to UI* coords
CGContextTranslateCTM(context, 0, img.size.height);
CGContextScaleCTM(context, 1.0, -1.0);
// set the blend mode to color burn, and the original image
CGContextSetBlendMode(context, kCGBlendModeColorBurn);
CGRect rect = CGRectMake(0, 0, img.size.width, img.size.height);
CGContextDrawImage(context, rect, img.CGImage);
// set a mask that matches the shape of the image, then draw (color burn) a colored rectangle
CGContextClipToMask(context, rect, img.CGImage);
CGContextAddRect(context, rect);
CGContextDrawPath(context,kCGPathFill);
// generate a new UIImage from the graphics context we drew onto
UIImage *coloredImg = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
//return the color-burned image
return coloredImg;
}
Use it like below...
yourImageView.image = [self imageNamed:#"yourImageName" withColor:[UIColor orangeColor]];
Here is the Swift version:
extension UIImage {
func colorizeWith(color: UIColor) -> UIImage {
UIGraphicsBeginImageContext(self.size)
let context = UIGraphicsGetCurrentContext()
color.setFill()
CGContextTranslateCTM(context, 0, self.size.height)
CGContextScaleCTM(context, 1.0, -1.0)
// set the blend mode to color burn, and the original image
CGContextSetBlendMode(context, kCGBlendModeNormal);
let rect = CGRectMake(0, 0, self.size.width, self.size.height);
CGContextDrawImage(context, rect, self.CGImage);
// set a mask that matches the shape of the image, then draw (color burn) a colored rectangle
CGContextClipToMask(context, rect, self.CGImage);
CGContextAddRect(context, rect);
CGContextDrawPath(context,kCGPathFill);
// generate a new UIImage from the graphics context we drew onto
let coloredImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
//return the color-burned image
return coloredImage;
}
}
You can try Ankish Jain's answer, it works for me.
theImageView.image = [theImageView.image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
[theImageView setTintColor:[UIColor redColor]];
CoreImage Color Filters work great for this kind of tasks - I find them slightly more straightforward than using the Core Graphic classes (CG...) : They work by allowing you to adjust the RGB and Alpha characteristics of the image I have been using them to change the white background of a QRCode to colored. RGBA of white is (1,1,1,1) in your case I believe you have to reverse the colour. Just check the CI documentation of Apple, there are a few dozen filters available CIColorMatrix is just one of them.
CIImage *beginImage = [CIImage imageWithCGImage:image.CGImage];
CIContext *context = [CIContext contextWithOptions:nil];
CIFilter *filtercd = [CIFilter filterWithName:#"CIColorMatrix" //rgreen
keysAndValues: kCIInputImageKey, beginImage, nil];
[filtercd setValue:[CIVector vectorWithX:0 Y:1 Z:1 W:0] forKey:#"inputRVector"]; // 5
[filtercd setValue:[CIVector vectorWithX:1 Y:0 Z:1 W:0] forKey:#"inputGVector"]; // 6
[filtercd setValue:[CIVector vectorWithX:1 Y:1 Z:0 W:0] forKey:#"inputBVector"]; // 7
[filtercd setValue:[CIVector vectorWithX:0 Y:0 Z:0 W:1] forKey:#"inputAVector"]; // 8
[filtercd setValue:[CIVector vectorWithX:1 Y:1 Z:0 W:0] forKey:#"inputBiasVector"];
CIImage *doutputImage = [filtercd outputImage];
CGImageRef cgimgd = [context createCGImage:doutputImage fromRect:[doutputImage extent]];
UIImage *newImgd = [UIImage imageWithCGImage:cgimgd];
filterd.image = newImgd;
CGImageRelease(cgimgd);
As I've answered here iPhone - How do you color an image? in my opinion the best way to colorize an image from iOS 7 is by using
myImageView.image = [[UIImage imageNamed:#"myImage"] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
and then change the tintColor of the imageView or whatever contains the image.

Affine Transforms + Demo App

I have a demo app here https://github.com/rdetert/image-transform-test
After importing an image, you can pinch, zoom, rotate the image. What I want to do is save out a 640x480 image (landscape mode) that looks identical to the live preview. So if there are 100px bars of empty space on the sides, I need the same empty bars in the final output (scaled appropriately).
This is proving to be more difficult than I thought it would be. I can't quite get it to come out right after days of working on it.
The magic method that generates the final image is called -(void)generateFinalImage
Good luck! ;)
EDIT
The green rectangle represents the actual area the imported image can be pinched, zoomed and rotated. The resolution on the iPhone 4S is 852x640, for example.
The blue rectangle is just a live preview for debugging and it's aspect ratio is the same as 640x480. The live preview could get very slow due to Core Image being very slow.
What I want to do is convert whatever is in the green rectangle to a 640x480 image. Notice the 852x640 is a slightly different aspect ratio than 640x480 too, but that isn't a huge problem.
Is your goal is to obtain just the exact copy of what you are editing, but with the size of the original image?
I guess it could be obtained by something like this:
- (UIImage *)padImage:(UIImage *)img to:(CGSize)size
{
if (size.width < img.size.width && size.height < img.size.height) return img;
size.width = MAX(size.width, img.size.width);
size.height = MAX(size.height, img.size.height);
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef context = CGBitmapContextCreate(NULL, size.width, size.height, 8, 0, colorSpace, kCGImageAlphaPremultipliedLast);
CGRect centeredRect = CGRectMake((size.width - img.size.width)/2.0, (size.height - img.size.height)/2.0, img.size.width, img.size.height);
CGContextDrawImage(context, centeredRect, [img CGImage]);
CGImageRef imageRef = CGBitmapContextCreateImage(context);
CGColorSpaceRelease(colorSpace);
CGContextRelease(context);
UIImage *paddedImage = [UIImage imageWithCGImage:imageRef];
CGImageRelease(imageRef);
return paddedImage;
}
// final image size must be 640x480
- (void)generateFinalImage
{
float rotatableCanvasWidth = 495.0;
float rotatableCanvasHeight = 320.0;
UIImage *tmp = self.importedRawImage;
CGSize size = self.importedRawImage.size;
NSLog(NSStringFromCGSize(size));
tmp = [self padImage:tmp to:CGSizeMake(rotatableCanvasWidth, rotatableCanvasHeight)];
CIImage *ciImage = [[CIImage alloc] initWithImage:[tmp imageWithTransform:self.importedImageView.transform]];
CGPoint center = CGPointMake(size.width / 2.0, size.height / 2.0);
CIContext *context = [CIContext contextWithOptions:nil];
CGRect r = ciImage.extent;
r.origin.x = (r.size.width - rotatableCanvasHeight) / 2.0;
r.origin.y = (r.size.height - rotatableCanvasWidth) / 2.0;
r.size.width = rotatableCanvasHeight;
r.size.height = rotatableCanvasWidth;
self.finalImage = [UIImage imageWithCGImage:[context createCGImage:ciImage fromRect:r] scale:1.0 orientation:UIImageOrientationUp];
self.finalImage = [self.finalImage resizedImage:CGSizeMake(100.0f, 134.0f) interpolationQuality:kCGInterpolationHigh];
self.previewImageView.image = self.finalImage;
}

Resources