Image contentMode issue with retina display - objective-c

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.

Related

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

UIImage in landscape programmatically

I have an image (small button) which looks perfect in Portrait Orientation, but my whole App is running in Landscape Right mode, however the image does not change to landscape.
I want to do it programmatically
I tried:
NSString *pathToImg = [[NSBundle mainBundle] pathForResource:#"DetonatorSmall" ofType:#"png"];
UIImage *img = [UIImage imageWithContentsOfFile:pathToImg];
UIImageView *imgView = [[UIImageView alloc] initWithImage:img];
imgView.transform = CGAffineTransformMakeRotation(3.14159265/2);
[button setImage:imgView.image forState:UIControlStateNormal];
But the image is still in portrait.
Any ideas what I can do?
Try This:
UIImage *img = [UIImage imageWithContentsOfFile:pathToImg];
[button setImage:img forState:UIControlStateNormal];
[button setTransform:CGAffineTransformMakeRotation(-M_PI / 2.0)];//Left
[button setTransform:CGAffineTransformMakeRotation( M_PI / 2.0)];//Right
I fixed it myself! :)
I added the image to a button, before it was drawn, so the button was the one I had to move. I applied the .transform to the imageview, but I had to do it fro the button :)
Can be closed

iOS UIAppearance Error

I'm building a file management app, and I occasionally get the following error while calling a UIImagePickerController or a MPMediaPickerController:
*** -[_UIImageViewPretiledImageCacheKey hash]: message sent to deallocated instance 0x140dc0
I recently gave my app a custom theme using iOS 5's UIAppearance API and thats when I started getting this error. By guessing and checking, I found the problematic lines of my code that cause this error:
UIImage *backButtonImage = [[UIImage imageNamed:#"backButton.png"] resizableImageWithCapInsets:UIEdgeInsetsMake(12, 16, 12, 8)];
[[UIBarButtonItem appearance] setBackButtonBackgroundImage:backButtonImage forState:UIControlStateNormal barMetrics:UIBarMetricsDefault];
UIImage *barButtonImage = [[UIImage imageNamed:#"barButton.png"] resizableImageWithCapInsets:UIEdgeInsetsMake(14, 12, 14, 12)];
[[UIBarButtonItem appearance] setBackgroundImage:barButtonImage forState:UIControlStateNormal barMetrics:UIBarMetricsDefault];
I have no idea how this code triggers the above error. Can you please explain to me the source of this error and provide a solution to fix it.
Thanks in advance for your help,
Guvvy
After some more thorough testing, I have reached the conclusion that this problem is limited to retina devices. The issue turned out to be in the #2x images. They had a odd numbered resolution (eg. 59px by 60px). All I did was recreate the image and changed the resolution to 60px by 60px and I never experienced the problem again.
I was kind of surprised by the solution as I saw no correlation between the error message and the line of code, but in the end, it was the images that caused this problem.
I had a similar problem, but my crash was caused by a resizable image in a UIImageView.
My resizable image has edge insets of top=30px, left=20px, bottom=1px, right=10px. The image is 43x45, so its resizable area is 13x14. I'm using iOS6, so I was able to workaround the problem by specifying UIImageResizingModeStretch as the resizingMode for -[UIImage resizableImageWithCapInsets:resizingMode:].
Works:
UIImage *image = [UIImage imageNamed:name];
UIImage *resizableImage = [image resizableImageWithCapInsets:edgeInsets resizingMode:UIImageResizingModeStretch];
Crashes with EXC_BAD_ACCESS or [_UIImageViewPretiledImageCacheKey hash]: message sent to deallocated instance 0xb14deb0 with NSZombieEnabled:
UIImage *image = [UIImage imageNamed:name];
UIImage *resizableImage = [image resizableImageWithCapInsets:edgeInsets];
I got the same for the following code
UIImage* image = [UIImage stretchableImageNamed:#"imageName"];
self.backgroundView = [[UIImageView alloc] initWithImage:image];
self.selectedBackgroundView = [[UIImageView alloc] initWithImage:image];
where self is UITableViewCell and stretchableImageNamed: is simply
+(UIImage*)stretchableImageNamed:(NSString*)name
{
UIImage *img = [UIImage imageNamed:name];
CGSize sz = img.size;
int left = (sz.width - 1.) / 2.;
int top = (sz.height - 1.) / 2.;
return [img resizableImageWithCapInsets:UIEdgeInsetsMake(top, left, top, left)];
}
this helped:
self.backgroundView = [[UIImageView alloc] initWithImage:[UIImage stretchableImageNamed:#"imageName"]];
self.selectedBackgroundView = [[UIImageView alloc] initWithImage:[UIImage stretchableImageNamed:#"imageName"]];

Saving UIImage with UIImagePNGRepresentation not preserving my layer modification

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.