Saving UIImage with UIImagePNGRepresentation not preserving my layer modification - objective-c

I'm loading an image from NSData. The original image was created as a JPG. When I attempt to set a corner radius and save to disk, I'm losing the changes I made. I'm saving to disk as a PNG as I presumed that an alpha channel would be created on the layers which needs to be preserved.
UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage imageWithData:data]];
[imageView.layer setMasksToBounds:YES];
[imageView.layer setCornerRadius:10.0f];
data = UIImagePNGRepresentation(imageView.image);
// save data to file with .png extension
The issue is that when I reload the image from the file system back into a UIImage, the corner radius is not visible.

CGContext can take a "screenshot".
UIGraphicsBeginImageContext(self.frame.size);
[self.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
// Now I use the "screenshot"
NSString *path = [NSHomeDirectory() stringByAppendingString:#"/image.jpg"];
if ([UIImageJPEGRepresentation(image, 1) writeToFile:path atomically:YES]) {
NSLog(#"save ok");
}
else {
NSLog(#"save failed");
}

You're setting the corner radius on the image view, not the image. The PNG representation is from the image, not the image view, so the corner radius is lost.

Related

drawAtPoint is eating memory

I am working on an iOS app. I need crop an image which is generate from PDF.
Sometimes, the image resolution can be very big.
I use follow code to generate the cropped image. My problem is the memory is increasing all the time. Never released.
- (UIImage *)croppedImageWithFrame:(CGRect)frame angle:(NSInteger)angle{
UIImage *croppedImage = nil;
CGPoint drawPoint = CGPointZero;
UIGraphicsBeginImageContextWithOptions(frame.size, YES, self.scale);
{
CGContextRef context = UIGraphicsGetCurrentContext();
//To conserve memory in not needing to completely re-render the image re-rotated,
//map the image to a view and then use Core Animation to manipulate its rotation
if (angle != 0) {
UIImageView *imageView = [[UIImageView alloc] initWithImage:self];
imageView.layer.minificationFilter = #"nearest";
imageView.layer.magnificationFilter = #"neareset";
imageView.transform = CGAffineTransformRotate(CGAffineTransformIdentity, angle * (M_PI/180.0f));
CGRect rotatedRect = CGRectApplyAffineTransform(imageView.bounds, imageView.transform);
UIView *containerView = [[UIView alloc] initWithFrame:(CGRect){CGPointZero, rotatedRect.size}];
[containerView addSubview:imageView];
imageView.center = containerView.center;
CGContextTranslateCTM(context, -frame.origin.x, -frame.origin.y);
[containerView.layer renderInContext:context];
}
else {
CGContextTranslateCTM(context, -frame.origin.x, -frame.origin.y);
[self drawAtPoint:drawPoint];
}
croppedImage = UIGraphicsGetImageFromCurrentImageContext();
}
UIGraphicsEndImageContext();
return croppedImage;
}
When I debug,
It burns 100MB in line
UIGraphicsBeginImageContextWithOptions(frame.size, YES, self.scale);
then when run into follow line, it burn another 150MB
[self drawAtPoint:drawPoint];
When run to follow line, it release 100MB
UIGraphicsEndImageContext();
after it's done, the 150MB never released
I thought UIGraphicsEndImageContext() should release all the 250MB. Why it's not?

Change UIImage imageOrientation metadata without affecting the image

I have an app which loads an image from the local disk and then displays it on a UIImageView. I want to set the image to aspect scale to fit.
The problem I'm having is that the imageOrientation is coming back as UIImageOrientationRight even though it's a portrait image and that's messing with how the aspect calculations are done.
I've tried a few methods of changing the meta data but both rotate the image when it gets displayed.
UIImageView *iv = [[UIImageView alloc] initWithFrame:self.frame.frame];
NSMutableString *path =[[NSMutableString alloc] initWithString: [[NSBundle mainBundle] resourcePath]];
[path appendString:#"/pic2.jpg"];
NSData *data = [NSData dataWithContentsOfFile:path];
UIImage *img = [UIImage imageWithData:data];
UIImage *fixed1 = [UIImage imageWithCGImage:[img CGImage]
scale:1.0
orientation: UIImageOrientationUp];
UIImage *sourceImage = img;
UIImage *fixed2 = [UIImage
imageWithCGImage:[img imageRotatedByDegrees:90].CGImage
scale:sourceImage.scale
orientation:UIImageOrientationUp];
iv.image = fixed1; // fixed2;
[iv setContentMode:UIViewContentModeScaleAspectFill];
[self.view addSubview:iv];
In the end I took a different approach and made the UIImageView 360 wide and placed it in the centre and this achieved the desired effect.

Best pratice to draw clear image in UIScrollView

I have a UIscrollView I'm displaying an image in it in this way
- (UIImage *)pageControlImageWithIndex:(NSInteger)index{
NSString *imagePath = [NSHomeDirectory() stringByAppendingFormat:#"/Documents/t%d.jpg",index];
NSFileHandle *fileHandle = [NSFileHandle fileHandleForReadingAtPath:imagePath];
return [UIImage imageWithData:[fileHandle readDataToEndOfFile]];
}
UIImage *image = [self pageControlImageWithIndex:pageNumber];
UIGraphicsBeginImageContext(CGSizeMake(320.0, 164));
[image drawInRect:CGRectMake(0, 0, 320.0, 164.0)];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
self.view.backgroundColor = [UIColor colorWithPatternImage:newImage];
but the image appear with some blur
while displaying the same image in this way in other View (inside UIImageView)
NSFileHandle *fileHandle = [NSFileHandle fileHandleForReadingAtPath:[NSHomeDirectory() stringByAppendingFormat:#"/Documents/t%d.jpg",topicNum]];
[topicPicImageView setImage:[UIImage imageWithData:[fileHandle readDataToEndOfFile]]];
produce this quality
HOW CAN I GET THE SAME QUALITY for the image in the UIScrollView ?
The image dimensions is 640 * 360
The Two image containers dimensions is 320 * 164
UIGraphicsBeginImageContext will create a context with a scale of 1.0, or non-retina. But you most likely want to create a context that matches the scale of your device. Use the new UIGraphicsBeginImageContextWithOptions(CGSize size, BOOL opaque, CGFloat scale) function.
Replace
UIGraphicsBeginImageContext(CGSizeMake(320.0, 164));
with
UIGraphicsBeginImageContextWithOptions(CGSizeMake(320.0, 164), YES, 0.0);
0.0 as scale parameter means "use device main screen scale". If your image has transparency you want to use NO as second parameter.

Showing only a portion of the original image in a UIImageView

How can i show only a portion of the original image in a UIImageView
This question may be very familiar and old, But the reason for asking again is,i could not find a workable idea with the help of those answers
Many said set image.contentMode = UIViewContentModeCenter; (but not working)
I need almost a rectangle containing the center of the original image,How do I get this ?
I do make this working,when i am displaying a static image to my app and setting Content mode of UIImageVie as Aspect Fill.
But this is not workable in the case when i am displaying an image from url and using NSData
Adding my code and the images
NSString *weburl = #"http://topnews.in/files/Sachin-Tendulkar_15.jpg";
UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(10, 50, 108, 86)];
NSURL *url = [NSURL URLWithString:weburl];
NSData *data = [NSData dataWithContentsOfURL:url];
imageView.image = [UIImage imageWithData:data];
[self.view addSubview:imageView];
If you added the UIImageView form XIB, you can find a "mode" property there and then you can see and set different modes from there (from Interface builder). Or by programatically, you can set different modes by
imageView.contentMode = UIViewContentModeCenter;
imageView.clipsToBounds = YES;
Try this:
self.imageView.layer.contentsRect = CGRectMake(0.25, 0.25, 0.5, 0.5);
self.imageView will display middle part of image. You can calculate itself the required values of CGRect ​
For this kind of output, you need to crop the image according to your requirement.
Cropping code as below which can be used.
-(UIImage *) CropImageFromTop:(UIImage *)image
{
CGImageRef imageRef = CGImageCreateWithImageInRect([image CGImage], CGRectMake(0, 12, image.size.width, image.size.height - 12));
UIImage *cropimage = [[[UIImage alloc] initWithCGImage:imageRef] autorelease];
CGImageRelease(imageRef);
return cropimage;
}
you try to scale image and then add image in UiImageView and set center that image then it is in center. code of scale image is
-(UIImage *)imageWithImage:(UIImage *)image scaledToSize:(CGSize)newSize{
UIGraphicsBeginImageContext(newSize);
[image drawInRect:CGRectMake(0, 0, newSize.width, newSize.height)];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
then you set the center of that image and add in the image view i hope this is work

Image contentMode issue with retina display

I have this UIButton, he has an image, on normal iPhone it works fine, the image contentMode is set to UIViewcontentModeCenter and its fine. but on retina, the image is not center, it's big and doesn't fit into the button frame.
Why is that and how can I fix it?
[theImageView setImage:Image forState:UIControlStateNormal];
[theImageButton setImage:Image forState:UIControlStateHighlighted];
[theImageButton setImage:Image forState:UIControlStateSelected];
[theImageButton setBackgroundColor:[UIColor clearColor]];
[theImageButton addTarget:self action:#selector(dismissKeyboard:) forControlEvents:UIControlEventAllTouchEvents];
theImageButton.imageView.contentMode = UIViewContentModeCenter;
The image loading:
- (UIImage *)loadScreenShotImageFromDocumentsDirectory
{
UIImage * tempimage;
NSArray *sysPaths = NSSearchPathForDirectoriesInDomains( NSDocumentDirectory, NSUserDomainMask, YES );
NSString *docDirectory = [sysPaths objectAtIndex:0];
NSString *filePath = [NSString stringWithFormat:#"%#/MeasureScreenShot.png", docDirectory];
tempimage = [[UIImage alloc] initWithContentsOfFile:filePath];
return tempimage;
}
I have to say, that the image that loaded into the contentMode is a screen shot that has been taken programmatically. maybe it has to do with it (anyway on normal display it works fine).
Thanks!
Sounds like you're getting a retina image, with 1.0 scale. You need to tell the system, that your image is actually 2.0, if you use contexts to capture screenshot, use
UIGraphicsBeginImageContextWithOptions(..., ..., 0.0);
0.0 tells it to use current device's main screen scale, or you can specify correct scale yourself.