crop UIImage function not work properly when photo take from camera.? - ios

I used crop function that crop image . It is work good when i take photo from photo library but when i use camera to take picture and crop the image. the crop function give me a wrong crop image .
My crop logic:
float zoomScale = 1.0 / [scrollView zoomScale];
CGRect rect;
rect.origin.x = [scrollView contentOffset].x * zoomScale;
rect.origin.y = [scrollView contentOffset].y * zoomScale;
rect.size.width = [scrollView bounds].size.width * zoomScale;
rect.size.height = [scrollView bounds].size.height * zoomScale;
UIImage *cropped = [self cropImage:imageView.image toRect:rect];//[UIImage imageWithCGImage:cr];
//CGImageRelease(cr);
return cropped;
static inline double radians (double degrees) {return degrees * M_PI/180;}
-(UIImage*)cropImage:(UIImage*)originalImage toRect:(CGRect)rect{
CGImageRef imageRef = CGImageCreateWithImageInRect([originalImage CGImage], rect);
CGBitmapInfo bitmapInfo = CGImageGetBitmapInfo(imageRef);
CGColorSpaceRef colorSpaceInfo = CGImageGetColorSpace(imageRef);
CGContextRef bitmap = CGBitmapContextCreate(NULL, rect.size.width, rect.size.height, CGImageGetBitsPerComponent(imageRef), CGImageGetBytesPerRow(imageRef), colorSpaceInfo, bitmapInfo);
if (originalImage.imageOrientation == UIImageOrientationLeft) {
CGContextRotateCTM (bitmap, radians(90));
CGContextTranslateCTM (bitmap, 0, -rect.size.height);
} else if (originalImage.imageOrientation == UIImageOrientationRight) {
CGContextRotateCTM (bitmap, radians(-90));
CGContextTranslateCTM (bitmap, -rect.size.width, 0);
} else if (originalImage.imageOrientation == UIImageOrientationUp) {
// NOTHING
} else if (originalImage.imageOrientation == UIImageOrientationDown) {
CGContextTranslateCTM (bitmap, rect.size.width, rect.size.height);
CGContextRotateCTM (bitmap, radians(-180.));
}
CGContextDrawImage(bitmap, CGRectMake(0, 0, rect.size.width, rect.size.height), imageRef);
CGImageRef ref = CGBitmapContextCreateImage(bitmap);
UIImage *resultImage=[UIImage imageWithCGImage:ref];
CGImageRelease(imageRef);
CGContextRelease(bitmap);
CGImageRelease(ref);
return resultImage;
}
what is the problem with my code ?
image taken from camera is not proper crop .
Please solve it .
I want whole bottle image see in first image that i have to set but when i press crop button and give me a wrong image . seein second image.

Related

Select and crop face image from photo image (ios)

I'm trying to get cropped image from photo. I have the following code that crop image that was got from ios face detection sdk:
- (UIImage *)scaleAndRotateImage:(CIFeature *)ciFeature image:(UIImage *)image {
static int kMaxResolution = 640;
CGImageRef imgRef = image.CGImage;
CGFloat width = CGImageGetWidth(imgRef);
CGFloat height = CGImageGetHeight(imgRef);
CGAffineTransform transform = CGAffineTransformIdentity;
CGRect bounds = CGRectMake(0, 0, width, height);
if (width > kMaxResolution || height > kMaxResolution) {
CGFloat ratio = width/height;
if (ratio > 1) {
bounds.size.width = kMaxResolution;
bounds.size.height = bounds.size.width / ratio;
} else {
bounds.size.height = kMaxResolution;
bounds.size.width = bounds.size.height * ratio;
}
}
CGFloat scaleRatio = bounds.size.width / width;
UIImageOrientation orient = image.imageOrientation;
switch(orient) {
case UIImageOrientationUp:
transform = CGAffineTransformIdentity;
break;
default:
[NSException raise:NSInternalInconsistencyException
format:#"Invalid image orientation"];
}
UIGraphicsBeginImageContext(bounds.size);
CGContextRef context = UIGraphicsGetCurrentContext();
if (orient == UIImageOrientationRight || orient == UIImageOrientationLeft) {
CGContextScaleCTM(context, -scaleRatio, scaleRatio);
CGContextTranslateCTM(context, -height, 0);
} else {
CGContextScaleCTM(context, scaleRatio, -scaleRatio);
CGContextTranslateCTM(context, 0, -height);
}
CGContextConcatCTM(context, transform);
CGContextDrawImage(UIGraphicsGetCurrentContext(), CGRectMake(0, 0, width, height), imgRef);
UIImage *returnImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return returnImage;
}
But how can I crop only face from the image (Like face image in box) because for now it changes original resolution of image?
If you want to crop your image with more conveniently and more user-defined, I recommend you to use the RSKImageCropper, its github location is here:https://github.com/ruslanskorb/RSKImageCropper
Because you want to crop the face's position, so the system's default method is not satisfy your requirement, you can learn from here:https://developer.apple.com/library/content/documentation/AudioVideo/Conceptual/CameraAndPhotoLib_TopicsForIOS/Articles/PickinganItemfromthePhotoLibrary.html#//apple_ref/doc/uid/TP40010408-SW1
The Core Graphic's crop image method:CGImageCreateWithImageInRect, is not easy to confirm the rect you want, because you for get the position of the face you should do a lot of work, the RSKImageCropper may be your convenient choise.

Why the PNG image resized and shows very well in UIImageView but quality not good when I draw it by CGContextDrawImage

I have a PNG (52x52) image file,if I show it in a UIImageView (16x16) , it is showed good.
But if I try to use CGContextDrawImage to draw, the quality is very bad.
Please see below detail code:
resizeImage is used to resize the image (copy from apple site).
drawStonesPng is do draw the image and called form CALayer:: drawInContext
- (UIImage*)resizeImage:(UIImage*)image toWidth:(NSInteger)width height:(NSInteger)height
{
// Create a graphics context with the target size
// On iOS 4 and later, use UIGraphicsBeginImageContextWithOptions to take the scale into consideration
// On iOS prior to 4, fall back to use UIGraphicsBeginImageContext
CGSize size = CGSizeMake(width, height);
if (NULL != UIGraphicsBeginImageContextWithOptions)
UIGraphicsBeginImageContextWithOptions(size, NO, 0);
else
UIGraphicsBeginImageContext(size);
CGContextRef context = UIGraphicsGetCurrentContext();
// Flip the context because UIKit coordinate system is upside down to Quartz coordinate system
CGContextTranslateCTM(context, 0.0, height);
CGContextScaleCTM(context, 1.0, -1.0);
// Draw the original image to the context
CGContextSetBlendMode(context, kCGBlendModeCopy);
CGContextDrawImage(context, CGRectMake(0.0, 0.0, width, height), image.CGImage);
// Retrieve the UIImage from the current context
UIImage *imageOut = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return imageOut;
}
-(void)drawStonesPng:(CGContextRef)ctx{
_cellWidth=16;
float x1,y1;
float f1=0.48;
// self.contentsScale = [UIScreen mainScreen].scale;
UIImage* resizedImageBlack = [self resizeImage:[UIImage imageNamed:#"blackstone52"] toWidth:_cellWidth*f1*2 height:_cellWidth*f1*2];
UIImage* resizedImageBlackShadow = [self resizeImage:[UIImage imageNamed:#"blackshadow"] toWidth:_cellWidth*f1*2 height:_cellWidth*f1*2];
CGImageRef imgBlack = [resizedImageBlack CGImage];
CGImageRef imgBlackShadow = [resizedImageBlackShadow CGImage];
CGFloat width = CGImageGetWidth(imgBlack), height = CGImageGetHeight(imgBlack);
// CGContextSetInterpolationQuality(ctx, kCGInterpolationHigh);
// CGContextSetShouldAntialias(ctx, true);
for(int y=0; y<_boardSize; y++) {
for(int x=0; x<_boardSize; x++) {
STONE_T stone = [MyGoController getStoneType:x y:y];
if(STONE_INVALID==stone){
CGContextClosePath(ctx);
return;
}
if(stone==STONE_BLACK){
x1=(x+1)*_cellWidth-_cellWidth*f1;
y1=(y+1)*_cellWidth-_cellWidth*f1;
// CGFloat scale = _cellWidth*0.9/width;
// NSLog(#"Scale: %f\nWidth: %f\nHeight: %f", scale, width, height);
// CGContextTranslateCTM(ctx, 0, height / scale);
// CGContextScaleCTM(ctx, 1.0, -1.0);
CGFloat scale = [[UIScreen mainScreen] scale];
self.contentsScale =[[UIScreen mainScreen] scale];
NSLog(#"Scale: %f\nWidth: %f\nHeight: %f", scale, width, height);
CGContextTranslateCTM(ctx, 0, width / scale);
CGContextScaleCTM(ctx, 1.0, -1.0);
CGContextDrawImage(ctx, CGRectMake(x1+1, y1+1, width/scale,width/scale), imgBlackShadow);
CGContextDrawImage(ctx, CGRectMake(x1, y1, width/scale,width/scale), imgBlack);
}
}
}
resizedImageBlack = [self resizeImage:[UIImage imageNamed:#"whitestone52"] toWidth:_cellWidth*f1*2 height:_cellWidth*f1*2];
resizedImageBlackShadow = [self resizeImage:[UIImage imageNamed:#"whiteshadow"] toWidth:_cellWidth*f1*2 height:_cellWidth*f1*2];
imgBlack = [resizedImageBlack CGImage];
imgBlackShadow = [resizedImageBlackShadow CGImage];
//draw white stones
for(int y=0; y<_boardSize; y++) {
for(int x=0; x<_boardSize; x++) {
STONE_T stone = [MyGoController getStoneType:x y:y];
if(stone==STONE_WHITE){
x1=(x+1)*_cellWidth-_cellWidth*f1;
y1=(y+1)*_cellWidth-_cellWidth*f1;
// CGFloat scale = _cellWidth*0.9/width;
// NSLog(#"Scale: %f\nWidth: %f\nHeight: %f", scale, width, height);
// CGContextTranslateCTM(ctx, 0, height / scale);
// CGContextScaleCTM(ctx, 1.0, -1.0);
CGContextDrawImage(ctx, CGRectMake(x1+1, y1+1, _cellWidth*f1*2,_cellWidth*f1*2), imgBlackShadow);
CGContextDrawImage(ctx, CGRectMake(x1, y1, _cellWidth*f1*2,_cellWidth*f1*2), imgBlack);
}
}
}
}
You need to set the content scale of the layer you're using :
CALayer theLayer = ....;
theLayer.contentsScale = [UIScreen mainScreen].scale

Resizing UITableView ImageView

How do I resize the UIImageView in a UITableViewCell? I'm passing in a large image (at least 100x100px), so the image itself shouldn't be the problem (it should scale down with the imageview)
cell.imageView.image = [UIImage imageNamed:#"unread.png"];
CGSize itemSize = CGSizeMake(25, 25);
UIGraphicsBeginImageContext(itemSize);
CGRect imageRect = CGRectMake(0.0, 0.0, itemSize.width, itemSize.height);
[cell.imageView.image drawInRect:imageRect];
cell.imageView.image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
Normally the UIImageView in the UITableViewCell is 43 points (or 86 pixels) in height and width. I'd like to size it down to 20 x 20 but this isn't doing anything. Am I missing something?
You can't change the frame of uiimageview of uitableviewcell. You can choose an option from the below
Create a custom cell and place a uiimageview at your requirement(which is the best solution and i prefer this one).
Use core graphics inside your cellForRowAtIndexPath:
CGSize itemSize = CGSizeMake(width, height);
UIGraphicsBeginImageContext(itemSize);
CGRect imageRect = CGRectMake(0.0, 0.0, itemSize.width, itemSize.height);
[cell.imageView.image drawInRect:imageRect];
cell.imageView.image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
I hope following function useful for you:
+(UIImage*)resizeImage:(UIImage *)image width:(int)width height:(int)height {
CGFloat targetWidth = width;
CGFloat targetHeight = height;
CGImageRef imageRef = [image CGImage];
CGBitmapInfo bitmapInfo = CGImageGetBitmapInfo(imageRef);
CGColorSpaceRef colorSpaceInfo = CGImageGetColorSpace(imageRef);
if (bitmapInfo == kCGImageAlphaNone) {
bitmapInfo = kCGImageAlphaNoneSkipLast;
}
CGContextRef bitmap;
if (image.imageOrientation == UIImageOrientationUp || image.imageOrientation == UIImageOrientationDown) {
bitmap = CGBitmapContextCreate(NULL, targetWidth, targetHeight, CGImageGetBitsPerComponent(imageRef), CGImageGetBytesPerRow(imageRef), colorSpaceInfo, bitmapInfo);
} else {
bitmap = CGBitmapContextCreate(NULL, targetHeight, targetWidth, CGImageGetBitsPerComponent(imageRef), CGImageGetBytesPerRow(imageRef), colorSpaceInfo, bitmapInfo);
}
// In the right or left cases, we need to switch scaledWidth and scaledHeight,
// and also the thumbnail point
if (image.imageOrientation == UIImageOrientationLeft) {
CGContextRotateCTM (bitmap, radians(90));
CGContextTranslateCTM (bitmap, 0, -targetHeight);
} else if (image.imageOrientation == UIImageOrientationRight) {
CGContextRotateCTM (bitmap, radians(-90));
CGContextTranslateCTM (bitmap, -targetWidth, 0);
} else if (image.imageOrientation == UIImageOrientationUp) {
// NOTHING
} else if (image.imageOrientation == UIImageOrientationDown) {
CGContextTranslateCTM (bitmap, targetWidth, targetHeight);
CGContextRotateCTM (bitmap, radians(-180.));
}
CGContextDrawImage(bitmap, CGRectMake(0, 0, targetWidth, targetHeight), imageRef);
CGImageRef ref = CGBitmapContextCreateImage(bitmap);
UIImage* newImage = [UIImage imageWithCGImage:ref];
CGContextRelease(bitmap);
CGImageRelease(ref);
return newImage;
}

App crashing due to memory warning

I am working on one photographic app in that I am adding 10 effects to one image. I am using some libraries for this. After sometime app is crashing . Its showing memory warning. I am using image after compression but still also app is crashing . Can any one tell me how to solve this memory warning . I am using this following code for image compression
-(UIImage *)resizeImage:(UIImage *)image {
int w = image.size.width;
int h = image.size.height;
CGImageRef imageRef = [image CGImage];
int width, height;
int destWidth = 640;
int destHeight = 480;
if(w > h){
width = destWidth;
height = h*destWidth/w;
} else {
height = destHeight;
width = w*destHeight/h;
}
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef bitmap;
bitmap = CGBitmapContextCreate(NULL, width, height, 8, 4 * width, colorSpace, kCGImageAlphaPremultipliedFirst);
if (image.imageOrientation == UIImageOrientationLeft) {
CGContextRotateCTM (bitmap, M_PI/2);
CGContextTranslateCTM (bitmap, 0, -height);
} else if (image.imageOrientation == UIImageOrientationRight) {
CGContextRotateCTM (bitmap, -M_PI/2);
CGContextTranslateCTM (bitmap, -width, 0);
} else if (image.imageOrientation == UIImageOrientationUp) {
} else if (image.imageOrientation == UIImageOrientationDown) {
CGContextTranslateCTM (bitmap, width,height);
CGContextRotateCTM (bitmap, -M_PI);
}
CGContextDrawImage(bitmap, CGRectMake(0, 0, width, height), imageRef);
CGImageRef ref = CGBitmapContextCreateImage(bitmap);
UIImage *result = [UIImage imageWithCGImage:ref];
CGContextRelease(bitmap);
CGImageRelease(ref);
return result;
}
and I am using that GPUImage library and I have added GPUImageView for displaying image.
Please help me if someone has any idea.
Thanks in advance.
You need to release colorspace:
CGColorSpaceRelease(colorspace);
This may be a reason of leak, but if you call resizeImage many times then it can be the reason of crashes

Constrain color burn to the inside of a CGPath

I have a closed path defined as a CGPath (actually, CGMutablePath).
I want to color burn a specific region of a UIImage defined by the path. I've been fiddling around with Core Graphics, but currently my only options are to color tint a rectangular area defined by a CGRect, not a path.
Can anyone point me in the right direction?
--Update
Using the help of Rob I managed to rotate the image I got from the camera 90 deg to let it appear correctly in the UIImageview..
Only problem I have left is the PATH i need to draw is still 90 degrees of, and out of scale. The code i currently use is as following:
- (UIImage*)applyColorFillWithPath:(CGMutablePathRef) path withColor:(UIColor*)color {
CGFloat targetWidth = self.size.width;
CGFloat targetHeight = self.size.height;
CGImageRef imageRef = [self CGImage];
CGBitmapInfo bitmapInfo = CGImageGetBitmapInfo(imageRef);
CGColorSpaceRef colorSpaceInfo = CGImageGetColorSpace(imageRef);
if (bitmapInfo == kCGImageAlphaNone) {
bitmapInfo = kCGImageAlphaNoneSkipLast;
}
CGContextRef context;
if (self.imageOrientation == UIImageOrientationUp || self.imageOrientation == UIImageOrientationDown) {
//UIGraphicsBeginImageContext(CGSizeMake(targetWidth, targetHeight));
context = CGBitmapContextCreate(NULL, targetWidth, targetHeight, CGImageGetBitsPerComponent(imageRef), CGImageGetBytesPerRow(imageRef), colorSpaceInfo, bitmapInfo);
} else {
//UIGraphicsBeginImageContext(CGSizeMake(targetHeight, targetWidth));
context = CGBitmapContextCreate(NULL, targetHeight, targetWidth, CGImageGetBitsPerComponent(imageRef), CGImageGetBytesPerRow(imageRef), colorSpaceInfo, bitmapInfo);
}
// set the fill color
//[color setFill];
if (self.imageOrientation == UIImageOrientationLeft) {
CGContextRotateCTM(context, radians(90));
CGContextTranslateCTM (context, 0, -targetHeight);
} else if (self.imageOrientation == UIImageOrientationRight) {
CGContextRotateCTM (context, radians(-90));
CGContextTranslateCTM (context, -targetWidth, 0);
} else if (self.imageOrientation == UIImageOrientationUp) {
// NOTHING
} else if (self.imageOrientation == UIImageOrientationDown) {
CGContextTranslateCTM (context, targetWidth, targetHeight);
CGContextRotateCTM (context, radians(-180));
}
CGContextDrawImage(context, CGRectMake(0, 0, targetWidth, targetHeight),imageRef);
CGContextBeginPath(context);
CGContextAddPath(context, path);
CGContextSaveGState(context);
CGContextClip(context);
CGContextSetBlendMode(context, kCGBlendModeNormal);
CGContextSetFillColorWithColor(context, color.CGColor);
CGContextFillRect(context, CGPathGetBoundingBox(path));
CGContextRestoreGState(context);
// Turn the bitmap context into a UIImage.
CGImageRef cgImage = CGBitmapContextCreateImage(context);
CGContextRelease(context);
UIImage *coloredImg = [UIImage imageWithCGImage:cgImage scale:1 orientation:UIImageOrientationUp];
CGImageRelease(cgImage);
//return the color-burned image
return coloredImg;
}
The following image is the result. De red rectangle is a representation of the CGPATH. The white square is actually the result of the above method on the path.
http://i41.tinypic.com/f1zbdi.png
I suppose I need to manually rotate the CGPATH 90 degrees using COS math's and what not.. Although I might oversee something.. ?
Set the context's clipping path to your path to constrain the affected pixels.
CGContextRef gc = myGraphicsContext();
CGMutablePathRef path = myMutablePathRef();
CGContextBeginPath(gc);
CGContextAddPath(gc, path);
CGContextSaveGState(gc); {
CGContextClip(gc);
// Do color burn. For example:
CGContextSetBlendMode(gc, kCGBlendModeColorBurn);
CGContextSetFillColorWithColor(gc, [UIColor redColor].CGColor);
CGContextFillRect(gc, CGPathGetBoundingBox(path));
} CGContextRestoreGState(gc);

Resources