Strange Image rotation after loading - ios

In my app, user can make a profile pic by uploading it from phone or taking one from the phone.
Everything works fine, and the user is able to do any of these operations smoothly and the profile pic looks great, at the time of setting it up.
But, when the user starts the app again, I fetch the path of the image and try to show it.
And it is shown, but it is, for some reason, rotated for 90 or 180 degrees!
So, once again, at the moment when the user takes or uploads a pic from the phone, it is not rotated strangely like this, only on the next app life cycle.
Here is some code:
-(void)setAvatar
{
NSMutableArray* imagePathArray = [[Model shared] loadDataForKey:#"avatar"];
NSString *imagePath = [imagePathArray objectAtIndex:0];
UIImage *image = [UIImage imageWithContentsOfFile:imagePath];
if (image!=nil)
_avatar.image = image;
}

I suppose the problem is because of skipping embedded metadata information. When you use Media Library to get an image (?) it includes orientation transformation info. After that you start to UIImage, but this class truncates all image metadata. That's why you see your image rotated after you save and reload it.
Accessing Image Metadata in iOS

Related

Saving images from web server to phone for image slider

I have an app where it pulls urls of images from a database and stores it in coredata. Then in my app view, there's a scrollview of imageviews, basically I'm trying to do an image slider. These images tend to get updated so it needs to load from the server. I load the image urls from the coredata, download them to uiimages and load them in my view. Problem is, it's really slow as I'm doing it at runtime.
I was wondering what's the best way to go about this. I was thinking of loading all the images to the phone first when the app launches? I tried looking for some sample code to point me to the right direction but I can only find code that saves images to the phone's camera roll and not to the app itself. Anyone could help pls? Thanks!
Here's a method that takes a UIImage, a target path (the directory you want to save the image to) and the filename for the image, and saves the image as a PNG file:
-(BOOL) saveImage:(UIImage *)image savePath:(NSString *)savePath filename:(NSString *)filename{
savePath = [savePath stringByAppendingPathComponent:filename];
NSData *sourceData = UIImagePNGRepresentation(image);
return [sourceData writeToFile:savePath atomically:YES];
}
You will need to store the image in the right location within the app's sandbox. For example, don't put them in the Documents folder as it may be rejected by Apple since you can recreate (or re-download) the images. You likely want to put them in the Library/Caches folder, and be prepared to re-download them if they are removed. See the iOS File System Programming Guide for details on this.
I would be concerned about downloading all the files at app start, since it will look like the app has frozen if it non-responsive while download a number of image files. You can download the images in the background and update the UI as the images finish downloading.
One method to do this would be to check if the image has already been downloaded (e.g., is it in the Library/Caches folder). If it is, then use it, otherwise use a placeholder image until the image is downloaded. For example:
if (isImageAvailable) {
displayedImageView.image = cachedImage;
} else {
displayedImageView.image = placeholderImage;
[self getImageAtURL:imageURL andThenDo:^(UIImage *image) {
// Replace placeholder image with downloaded image
displayedImageView.image = image;
}];
}
Replace isImageAvailable with a method that checks for the existence of the image file in the Library/Caches folder. displayedImageView is the UIImageView you are displaying the image with.
The getImageAtURL method would look something like:
-(void)getImageAtURL:(NSURL *)url andThenDo:(void(^)(UIImage *image))completionBlock{
// Run on background thread
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
UIImage *image;
// Insert code to download image...
// Switch to main (UI) thread to allow updating the UI
dispatch_sync(dispatch_get_main_queue(), ^{
completionBlock(image);
});
});
}
You might not need to download images to your application, I can suggest better you use image url it self to load images from server it self.
To load images from server u may use following:
UIImage* yourImageview = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:your.image_url]]];
Downloading all images will also slow down your app.

UIImageView not releasing memory (according to VM Tracker) - Low Memory Warnings & Terminate

I'm really struggling with running out of memory in my app. The are the basic operations that I'm performing, as specified below. Note that whenever a user takes a picture with the camera, I save two different versions of it--one is a preview (for fast loading), and one with high quality for zooming and marking up later.
Here is a list of my order of operations:
At app launch, show thumbnails of images that have been taken in the app (obviously, at first launch of the app, this list is empty).
Touch camera button to launch the UIImagePickerController
User takes a photo and saves it (again, a preview is saved and a full scale photo is saved)
The list of thumbnails refreshes and shows the new preview image. Again, the overall size of "Image IO" in the VM Tracker instrument is still very small (increased by maybe 0.5MB tops).
User touches one of the preview images, which launches a different view controller that does the following:
Create new UIImageView, load the image, add as a subview to View Controllers view
Suddenly, "Image IO" jumps by 30MB.
The wouldn't be a big deal, but when I go back (navigation controller pop), neither the "Image IO" type nor the "Dirty" type decreases in size. It's as if the UIImageView is not being destroyed. Every time I push this view controller and load an image, the size increases by 30MB, and popping never decreases it.
I'm using ARC, so I'm not calling release myself, but I would expect that it would be destroyed when I pop the view controller.
Just FYI, the settings I'm using for saving the preview and the full image are:
Preview: [UIImageJPEGRepresentation([UIImage imageWithImage:image scaledToSize:CGSizeMake(300, 400)], 0.4f) writeToFile:previewPath atomically:NO];
Full: [UIImageJPEGRepresentation(image , 0.8f) writeToFile:imagePath atomically:NO];
My main concern is (1) figuring out how to get rid of the memory used from the UIImage after I pop the containing view controller, but I'd also like to know (2) why the image is 30MB when loaded.
i'm worked on image editor app and this help me lot for reduce memory use.Try this
don't load images with [UIImage imageNamed:] for load image in ImageView,it's cause memory issue when no.of images are more,
use this,
NSString * imgpath= [ [ NSBundle mainBundle] pathForResource:#"imageName" ofType:#"png"];
ImageView.image=[UIImage imageWithContentsOfFile: imgpath];
As suggested by #Matic Oblak...
(1) I have already seen similar problem with image view, try setting its image to "nil" before popping the controller and see if the problem persists.
RESULT: I explicitly set the UIImage AND the UIImageView to nil (not sure if both are needed), and sure enough, it released the memory.

IOS Comparing UIImage Data [duplicate]

This question already has answers here:
Comparing UIImage
(4 answers)
Closed 8 years ago.
I have a UIImageView that holds a cover photo for a user. Through the xcode IDE I added a placeholder image that acts as a stock cover photo. When the user clicks on the cover photo I need a way to tell if the image inside the UIImageView is the stock cover photo or another photo that the user has added. The image is never nil. Currently I am doing it by comparing the image data of the current cover photo to the image data generated buy creating an image from the stock cover photo image file.
This is what I have:
if ([UIImagePNGRepresentation(_coverPhoto.image) isEqualToData:UIImagePNGRepresentation([UIImage imageNamed:#"stockCoverPhoto.png"])])
{
[self loadPhoto:1];
}
Comparing the _coverPhoto.image to UIImage imageNamed:#"stockCoverPhoto.png" produced buggy results when the app was closed and reopened within the same session. There must be a better way to do this, I need my code to be as efficient as possible and comparing two NSData structures to one another seems unnecessary.
try with this
UIImage *img = [UIImage imageNamed:#"some.png"];
UIImage *img1 = [UIImage imageNamed:#"some1.png"];
NSData *dataObj1 = UIImagePNGRepresentation(img);
NSData *dataObj2 = UIImagePNGRepresentation(img2);
BOOL test = [dataObj1 isEqualToData:dataObj2];
if(test)
//is Equal
and other answer is
NSData compare to NSData in percents
NSData isEqualtoData
I suppose user will not add this picture every time he start the app. I don't see the problem at all. Just use some property for this, handle it after loading user picture and save it to NSUSerDefaults, cloud or somewhere...
// your class interface
#property (nonatomic) BOOL isUserPictureLoaded;
// first time run save isUserPictureLoaded = NO to NSUserDefaults
// if user saves own picture, set isUserPictureLoaded = YES and save to NSUserDefaults

Strange issue with loading an UIImage from core dara directly using KVC

I am in the middle of an app project with core data where I stricty use KVC only with regard to the NSManagedObjects. The purpose of consequentally doing that is simply to get an understanding of advantages and disadvanages. I may have discovered a disadvangate. However, I cannot explain why.
I came across this when I used some very well established principle (used that in other apps already) of saving a scetch that the user drew with his fingers (a signature to a document) in core data and fetch and display or print to PDF respectively it later.
It turned out that I was able to get the UIImage from the view, store it in core data and instanly receive it from core data again using KVC (no save/fetch in between) and display it in another view for testing purposes. But I was unable to actually save it, fetch the data from persistant storage and re-display it on the screen.
So I did a lot of debugging, analysed the sqlite file etc. Eventually I nailed it down to the following strange behaviour:
Situation:
The image was stored into core data successfully by doing this:
[self.detailItem setValue:UIImagePNGRepresentation(image) forKey:kSignatureImage];
with image being an UIImage object and self.detailItem is the NSManagedOBject. Keys and references and everything is fine.
Then it comes to displaying the view again. The following is independent from whether the context was saved in between or even the app was closed and restartet or not:
self.signatureCanvas.image = [UIImage imageWithData:[self.detailTextLabel valueForKey:kSignatureImage]];
with self.signatureCanvas beeing an UIImageView subclass object. The image is not shown on screen.
NSData *data = [self.detailItem valueForKey:kSignatureImage];
NSLog(#"UIImage a: %#", [UIImage imageWithData:[self.detailTextLabel valueForKey:kSignatureImage]]);
NSLog(#"UIImage b: %#", [UIImage imageWithData:data]);
self.testImage.image = [UIImage imageWithData:[self.detailTextLabel valueForKey:kSignatureImage]];
self.signatureCanvas.image = [UIImage imageWithData:data];
self.testImage is a second plain UIImageView withn the same view (but smaller). Now the image is visible in signatureCanvas but not in testImage. (could be vice versa, tried that)
The output give a hint on what was happening but no actual explanation:
2013-03-22 12:43:37.746 MyApp[1595:c07] UIImage a: (null)
2013-03-22 12:43:37.769 MyApp[1595:c07] UIImage b: <UIImage: 0x7c973a0>
Until now I would have thought that the lines of code were kinda equivalent and that the compiler may even optimize the data object away. But why is the image (null) in one case and not in the other.
So I found the problem root cause and a workaround. Therefore this is not urgent any more. But I do not understand it. Any clues?
Environment is: SDK 6.1, xcode 4.6, ARC, core data on sqlite, iPad only so far. All this happens in a UITableViewCell subclass (prototype cell within storyboard) naturally in a UITableViewController subclass.
I assume that self.detailTextLabel in
self.testImage.image = [UIImage imageWithData:[self.detailTextLabel valueForKey:kSignatureImage]];
should be self.detailItem.

Loading images into memory in iPhone App

I have an UImageView and on click of an button i want to change the UImage in the UImageView. App has 22 UImages with each image exceeding 5 mb size , so the UImageView takes some time to load an image when the button is clicked , is there a way by which we can load these images into the memory so that image view takes lesser time to show the image?
I use the following code to set the image :
[ImageView setImage:[UIImage imageNamed:#"ImageName.jpg"]];
basically i want on swipe the images to be changed , e.g. if a user swipes from right to left the app must show the next image and on left to right click the back image be loaded . please suggest .
like #Gobot mentioned it is the best way du reduce the size of your pictures. For the swipe there is no need to use big pictures like this. You could just create two folders, one with small sized pictures and another with bigger one. If you swipe through, you just use the small pictures. If a user taps a picture you could get the name of the selected UIImage and load just this single picture. That way you also can provide high quality pictures for zooming in. And keep in mind, that your app package gets also bigger the more pictures you have included.
There is a good explanation in a WWDC Stream: iOS App Performance: Graphics and Animations
I also created a method inside a NSMutableArray category for loading all my UIImages once. You could use this method inside viewDidLoad:
- (NSMutableArray *)getImagesWithStartSuffix:(NSString *)start
andEndSuffix:(NSString *)end{
NSMutableArray *imageArray = [[NSMutableArray alloc] init];
for (int i = 1; i < 100 + 2; i++) {
NSString *fileName = [NSString stringWithFormat:#"%#%d%#.jpg",
start, i, end];
if([self fileExistsInProject:fileName]){
[imageArray addObject:[UIImage imageNamed:fileName]];
} else {
break;
}
}
return imageArray;
}
There is also a very easy way to change the size of your pictures by writing an Apple Script. You could run a loop over all pictures and resize them all this way. This is the easiest way and you don't have to use any tools like Gimp or PS:
do shell script "sips [path_to_file]/picture1.jpg -z 666 1000 --out [path]/changedSize/picture1_small.jpg"
From the Documentation:
This method looks in the system caches for an image object with the specified name and returns that object if it exists. If a matching image object is not already in the cache, this method loads the image data from the specified file, caches it, and then returns the resulting object.
if it takes too long, you may want to add a progress indicator in your app till the full view is generated/loaded then display it on your screen.
The first and simplest option would be to reduce your images under 5MB. Do they really need to be that big? Are they thumbnails? The more complex option would be to load/cache images in a background thread (asynchronously) using dispatch queues.

Resources