Crop and save visible region of UIImageView using AspectFill - ios

I have a fullscreen UIImageView with a image in it set to AspectFill (full bleed), how can I save only the visible portion of the image when its using the Aspect Fill content mode?
CGRect visibleRect;
visibleRect.size= mImageView.frame.size;
CGImageRef cropped_img = CGImageCreateWithImageInRect(mImageView.image.CGImage, visibleRect);
UIImage *finalImage = [[UIImage alloc]initWithCGImage:cropped_img];
UIImageWriteToSavedPhotosAlbum(finalImage, nil, nil, nil);
This is my current code, cropping and saving works, its just not cropping correctly. Any ideas?

Try this:
UIGraphicsBeginImageContext(mImageView.frame.size);
CGContextRef context = UIGraphicsGetCurrentContext();
CGImageRef image = CGBitmapContextCreateImage(context);
width = CGImageGetWidth(image);
height = CGImageGetHeight(image);
CGImageRef cropped_img = CGImageCreateWithImageInRect(image, CGRectMake(0, 0, width, height));
// save...
CGImageRelease(image);
UIGraphicsEndImageContext();

Related

Unable to set frame of masked Image - Objective C

I have two images one is background image and one is masked image.
I am cropping background image based on masked image.
Background Image With Mask Image:
Result Image:
Following method is being used for cropping:
- (UIImage*) maskImage:(UIImage *)image withMask:(UIImage *)maskImage {
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGImageRef maskImageRef = [maskImage CGImage];
// create a bitmap graphics context the size of the image
CGContextRef mainViewContentContext = CGBitmapContextCreate (NULL, maskImage.size.width, maskImage.size.height, 8, 0, colorSpace, kCGImageAlphaPremultipliedLast);
CGColorSpaceRelease(colorSpace);
if (mainViewContentContext==NULL)
return NULL;
CGFloat ratio = 0;
ratio = maskImage.size.width/ image.size.width;
if(ratio * image.size.height < maskImage.size.height) {
ratio = maskImage.size.height/ image.size.height;
}
CGRect rect1 = {{0, 0}, {maskImage.size.width, maskImage.size.height}};
CGRect rect2 = {{-((image.size.width*ratio)-maskImage.size.width)/2 , -((image.size.height*ratio)-maskImage.size.height)/2}, {image.size.width*ratio, image.size.height*ratio}};
CGContextClipToMask(mainViewContentContext, rect1, maskImageRef);
CGContextDrawImage(mainViewContentContext, rect2, image.CGImage);
// Create CGImageRef of the main view bitmap content, and then
// release that bitmap context
CGImageRef newImage = CGBitmapContextCreateImage(mainViewContentContext);
CGContextRelease(mainViewContentContext);
UIImage *theImage = [UIImage imageWithCGImage:newImage];
CGImageRelease(newImage);
// return the image
return theImage;
}
Issue
Problem I am facing is that the mask Image is not taking the actual frame as shown above in background with mask image.
I tried playing with ratio and rect1 and rect2 but couldn't acheive the desired result.
Expected Image:
Image with exact frame of masked Image.
It would be great if someone show me the light.

How to get a masked UIImage without bad resolution?

I have an iOS application. I take a picture from my camera and I save this then crop this with a mask. The first image from the camera is saved correctly, but when I apply the mask it is saved with a low resolution and a stretched image.
I'm using this Objective-C code into my application to apply the mask.
- (UIImage*) maskImage:(UIImage *)image withMask:(UIImage *)mask_Image {
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
//UIImage *maskImage = maskImage1;
CGImageRef maskImageRef = [mask_Image CGImage];
// create a bitmap graphics context the size of the image
CGContextRef mainViewContentContext = CGBitmapContextCreate (NULL, mask_Image.size.width, mask_Image.size.height, 8, 0, colorSpace, kCGImageAlphaPremultipliedLast);
if (mainViewContentContext==NULL)
return NULL;
CGFloat widthratio = 0;
CGFloat heightratio = 0;
widthratio = mask_Image.size.width / image.size.width;
heightratio = mask_Image.size.height / image.size.height;
CGRect rect1 = {{0, 0}, {mask_Image.size.width, mask_Image.size.height}};
CGRect rect2 = {{-((image.size.width*widthratio)-mask_Image.size.width)/2 , -((image.size.height*heightratio)-mask_Image.size.height)/2}, {image.size.width*widthratio, image.size.height*heightratio}};
CGContextClipToMask(mainViewContentContext, rect1, maskImageRef);
CGContextDrawImage(mainViewContentContext, rect2, image.CGImage);
// Create CGImageRef of the main view bitmap content, and then
// release that bitmap context
CGImageRef newImage = CGBitmapContextCreateImage(mainViewContentContext);
CGContextRelease(mainViewContentContext);
UIImage *theImage = [UIImage imageWithCGImage:newImage];
CGImageRelease(newImage);
// return the image
NSData* imageData = UIImagePNGRepresentation(theImage); // get png representation
UIImage* pngImage = [UIImage imageWithData:imageData];
UIImageWriteToSavedPhotosAlbum(pngImage, nil, nil, nil);
return theImage;
}
I want get this correctly like:
I take my picture from the camera:
I apply my mask image to the camera image in the position that I wanted:
And I get my cropped image masked:
How can I get the correct masked image?

iOS how to draw a part of image to a specific rect?

I want to crop a 200*200 image, the cropped part is (x=10,y=10,w=50,h=50). and drawing this part to new 500*500 image, the new rect is (x=30,y=30,w=50, h=50), how to do it?
I can get the part of image with the following method
- (UIImage*) getSubImageWithRect: (CGRect) rect {
UIGraphicsBeginImageContext(rect.size);
CGContextRef context = UIGraphicsGetCurrentContext();
// translated rectangle for drawing sub image
CGRect drawRect = CGRectMake(-rect.origin.x, -rect.origin.y, self.size.width, self.size.height);
// clip to the bounds of the image context
// not strictly necessary as it will get clipped anyway?
CGContextClipToRect(context, CGRectMake(0, 0, rect.size.width, rect.size.height));
// draw image
[self drawInRect:drawRect];
// grab image
UIImage* subImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return subImage;
}
Lets try using following code chunk
- (UIImage*) getSubImageFromImage:(UIImage *)image
{
// translated rectangle for drawing sub image
CGRect drawRect = CGRectMake(10, 10, 50, 50);
// Create Image Ref on Image
CGImageRef imageRef = CGImageCreateWithImageInRect([image CGImage], rect);
// Get Cropped Image
UIImage *img = [UIImage imageWithCGImage:imageRef];
CGImageRelease(imageRef);
return img;
}

How to crop center part of large image in iOS?

When a image is cropped from the center then crop image will take the aspect ratio of source image,But According to my requirement, aspect ratio will be change with new crop size.
I want to get exact center part of image with new aspect ratio.For example a large image is of size (320*480) then I want to crop center part of image of size (100,100) and aspect ratio will also be 100*100 ,No outer white or black part is required and image quality will be high.
Cropping function :
- (UIImage *)cropImage:(UIImage*)image andFrame:(CGRect)rect {
//Note : rec is nothing but the image frame which u want to crop exactly.
rect = CGRectMake(rect.origin.x*image.scale,
rect.origin.y*image.scale,
rect.size.width*image.scale,
rect.size.height*image.scale);
CGImageRef imageRef = CGImageCreateWithImageInRect([image CGImage], rect);
UIImage *result = [UIImage imageWithCGImage:imageRef
scale:image.scale
orientation:image.imageOrientation];
CGImageRelease(imageRef);
return result;
}
Please help me.
This might run
- (UIImage *)imageByCroppingImage:(UIImage *)image toSize:(CGSize)size
{
// not equivalent to image.size (which depends on the imageOrientation)!
double refWidth = CGImageGetWidth(image.CGImage);
double refHeight = CGImageGetHeight(image.CGImage);
double x = (refWidth - size.width) / 2.0;
double y = (refHeight - size.height) / 2.0;
CGRect cropRect = CGRectMake(x, y, size.height, size.width);
CGImageRef imageRef = CGImageCreateWithImageInRect([image CGImage], cropRect);
UIImage *cropped = [UIImage imageWithCGImage:imageRef scale:0.0 orientation:self.imageOrientation];
CGImageRelease(imageRef);
return cropped;
}
var imageView = UIImageView()
// height and width values corresponds to rectangle height and width
imageView = UIImageView(frame: CGRectMake(0, 0, width, height ))
imageView.image = UIImage(named: "Your Image Name")
// by setting content mode to .ScaleAspectFill image centrally fill in imageView. image might appear beyond image frame.
imageView.contentMode = .ScaleAspectFill
// by setting .clipsToBouds to true, image set to image frame.
imageView.clipsToBounds = true
view.addSubview(imageView)
// Work this code
-(UIImage *)croppedImage
{
UIImage *myImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
[self.bezierPath closePath];
CGContextSetRGBStrokeColor(UIGraphicsGetCurrentContext(), 0.0, 0.0, 0.0, 0.0);
_b_image = self.bg_imageview.image;
CGSize imageSize = _b_image.size;
CGRect imageRect = CGRectMake(0, 0, imageSize.width, imageSize.height);
UIGraphicsBeginImageContextWithOptions(imageSize, NO, [[UIScreen mainScreen] scale]);
[self.bezierPath addClip];
[_b_image drawInRect:imageRect];
UIImage *croppedImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return croppedImage;
}
Calculate crop rect from image
float imgHeight = 100.0f; //Any according to requirement
float imgWidth = 100.0f; //Any according to requirement
CGRect cropRect = CGRectMake((largeImage.size.width/2)-(imgWidth/2),largeImage.size.height/2)-(imgHeight/2),imgWidth,imgHeight);
Now crop it
CGImageRef imageRef = CGImageCreateWithImageInRect([largeImage CGImage], cropRect);
// or use the UIImage wherever you like
UIImage *croppedImg = [UIImage imageWithCGImage:imageRef]];
CGImageRelease(imageRef);

Cropping and scaling a UIImage properly

I'm trying to crop a image into a square shape, and then scale it to a size 200x200. Here's the code I use, but it's not really working for me. The image I get is sometimes in a different orientation, or isn't cropped from the center, or is wider than it should be.
float scale = _avatar.image.scale;
UIImageOrientation orientation = _avatar.image.imageOrientation;
if(_avatar.image.size.width < _avatar.image.size.height){ // avatar is a UIImageView
float startingY = (_avatar.image.size.height-_avatar.image.size.width)/2; // image is taller, determine the origin of the width-sized square, which will be the new image
CGImageRef imageRef = CGImageCreateWithImageInRect([_avatar.image CGImage], CGRectMake(0, startingY, _avatar.image.size.width, _avatar.image.size.width));
_avatar.image = [UIImage imageWithCGImage:imageRef scale:scale orientation:orientation];
CGImageRelease(imageRef);
} else {
float startingX = (_avatar.image.size.width-_avatar.image.size.height)/2; // image is wider, determine the origin of the height-sized square, which will be the new image
CGImageRef imageRef = CGImageCreateWithImageInRect([_avatar.image CGImage], CGRectMake(startingX, 0, _avatar.image.size.height, _avatar.image.size.height));
_avatar.image = [UIImage imageWithCGImage:imageRef scale:scale orientation:orientation];
CGImageRelease(imageRef);
}
UIGraphicsBeginImageContextWithOptions(CGSizeMake(200, 200), YES, 0.0);
[_avatar.image drawInRect:CGRectMake(0, 0, 200, 200)];
UIImage *scaledImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
How it must be done to achieve the correct result?
I would suggest you to use this category for UIImage posted on github. They are also really simple classes and you can also use them to learn what is under the hood.
The UIImage has done all the coordinate and orientation tricks for you. So you should not use the width and height from an UIImage object to caculate the square's coordinate. You can take advantages of the UIKit to crop an image.
CGFloat startingX = 0;
CGFloat startingY = 0;
CGFloat squareWidth;
if(_avatar.image.size.width < _avatar.image.size.height){ // avatar is a UIImageView
startingY = (_avatar.image.size.height-_avatar.image.size.width)/2; // image is taller, determine the origin of the width-sized square, which will be the new image
squareWidth = _avatar.image.size.width;
} else {
startingX = (_avatar.image.size.width-_avatar.image.size.height)/2; // image is wider, determine the origin of the height-sized square, which will be the new image
squareWidth = _avatar.image.size.height;
}
UIGraphicsBeginImageContextWithOptions(CGSizeMake(squareWidth, squareWidth), YES, 0.0);
[_avatar.image drawAtPoint:CGPointMake(-startingX, -startingY)]; // Make an offset to draw part of the image
UIImage *croppedImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
UIGraphicsBeginImageContextWithOptions(CGSizeMake(200, 200), YES, 0.0);
[croppedImage drawInRect:CGRectMake(0, 0, 200, 200)];
UIImage *scaledImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

Resources