Ignoring iOS high-resolution #2x files - iphone

I have an app with a large number of images (1000+). I have a database table which contains all the filenames for these images. Images are loaded on demand based on this filename using UIImage* image = [UIImage imageNamed:...]
Due to the large number of images, I would like to programmatically test to ensure all image that are included in the database are in fact present in the project. To achieve this, I'm pulling all filenames from the table, looping over each filename, running the above code, and checking to see if image != nil. This works just fine.
The problem is that I would like to confirm that both normal resolution and high resolution (#2x) images are there. If the high-resolution file is present but the normal-resolution file is not, my code will not detect this.
Is there some way I can achieve this without having the run this process twice, once per resolution type? Can I force the SDK to ignore #2x files?

You should just use NSFileManager. It will probably be much quicker since it won't actually load the contents of the image files. For each fileName, use NSFileManager's fileExistsAtPath method to check for the image. Then, append "#2x" to the base name to check for the 2x image.

I would use NSBundle to locate the files so the UIImage doesn't have to be loaded into memory, you could use something like...
NSBundle *myBundle = [NSBundle mainBundle];
if([myBundle pathForResource:#"MyImage" forType: #"png"] == nil){
// low res image isn't there
}
if([myBundle pathForResource:#"MyImage#2x" forType: #"png"] == nil){
// high res image isn't there
}
Should be much faster...

Related

Load an Image from URL by many threads

I'm loading an image from URL into my app. The image size is large (around 1.5Mb). How can I use many threads (ex: 2 threads) to load this image to improve the speed? If using one thread to load this image, it takes me around 5s and I want to reduce this duration.
You are correct. 1.5Mb is a big image and the way to optimise is NOT to use many threads. Although you are on the right track. The technique is called "slicing" and is heavily used on web to load images faster. So take a image and slice it into 3 or 4 smaller pics (and not more) in your server. When rendering call these 4 images all at once. It will load faster than one big pic. Also this lessens the "perceived" latency for the end-user.
Also, when you slice up an image, it makes it easier to reduce the number of colors necessary to display that portion of the image, thus reducing your file size (sometimes fairly significantly).
As an example Google does used to do this for its main logo in its main search page. See 4 split us images of its logo?
The downside of slicing is that it increases maintenance costs. Some one has to maintain these image splits and make sure nothing goes amiss as the app keeps changing.
Please Try the following Code:
//in .h file declare the following objects:
IBOutlet UIImageView *imgTest;
-(IBAction)buttonTapped:(id)sender;
-(void)LoadImage:(NSString *) irlString;
-(void)setImage:(NSData *) imgData;
//in .m file write the following code:
-(IBAction)buttonTapped:(id)sender
{
[self performSelectorOnMainThread:#selector(LoadImage:) withObject:#"http://www.google.com/images/errors/logo_sm.gif" waitUntilDone:NO];
}
-(void)LoadImage:(NSString *) urlString
{
NSURL *imgURL=[NSURL URLWithString:urlString];
NSData *imgData=[NSData dataWithContentsOfURL:imgURL];
[self performSelectorInBackground:#selector(setImage:) withObject:imgData];
}
-(void)setImage:(NSData *) imgData;
{
imgTest.image=[UIImage imageWithData:imgData];
}
you can use activity indicator while loading the image as well. Start it in the buttonTapped method and stop it in the setImage method.
i hope this will help you.

How to avoid image duplication in image gallery of iOS device?

I want to store the images to photo gallary. But if images are already available at photo gallary then how to distinguish for whether imgaes are already exists or not? I didnt find property like unique identifier or should i compare by taking data in the form of NSdata?
thanks..
You can maintain a dictionary of hashes for each the image in the photo gallery, and then show only additional images who do not hashes are not present in the dictionary
As a reminder, you can check for an object in a dictionary by doing:
if ([myDictionary objectForKey:variableStoringImageHash] == nil) {
//No such image present
}
else {
//image is present
}
For a bit about hashing an image, this might help:
iPhone: fast hash function for storing web images (url) as files (hashed filenames)
I am not sure if what eitan27 says will work so as an alternative I would say that your best hope is comparing NSData objects. But this as you can see will become very tedious as there will be n number of images in library and comparing each one for repetition does't make sense , still if you want to compare data you look at this answer which will give you a fraction of how much the data is matching.

How to Check if an image is valid on iPhone

How to Check if an image is valid
For example, when I cached an image which was downloaded only half and failed, and this image is invalid, then I want to know it's an invalid image and download again.
(When I use the broken image, Xcode console logs an error:
ImageIO: PNG IDAT: CRC error )
So I want find a mechanism to check image's validation
for different kinds of JPEG,PNG,etc
anybody has some clues?
I would start by checking for valid header.
Secondly the footer. Usually the last 8 bytes uint values in order are
'73,69,78,68,174,66,96,130'.
This converted into a Int64 equals 5279712195050102914
This should do for a png :)
if (memcmp(img_bytes, "\211PNG", 4) != 0||OSReadBigInt64(img_bytes,(length - 8))!=5279712195050102914)
{
//Bad Data! Free your data and return or something
}
It happens because you are using same class to download image file from server and you request consequent download of same file, while it is already downloading that file, which fails the earlier one file download and results in partly downloaded file.
I suggest you to get the file size of the image & compare with the image file just downloaded.
For loading images from the network there are two obvious failure cases:
The downloaded file was not an image at all.
The downloaded data only contains part of the image data.
For the first case nil checking the return value of various UIImage methods is probably the best way to handle this error case.
The following class methods on UIImage will return nil if the image could not be initialized with the data it was provided: + (UIImage *)imageWithData:(NSData *)data and + (UIImage *)imageWithContentsOfFile:(NSString *)path.
Code that does the nil check might look like this:
UIImage *image = [UIImage imageWithContentsOfFile:pathToImage];
if (image) {
// The image was loaded. Display it
}
else {
// The image was not loaded. Redownload or display a placeholder, etc...
}
For the second failure case it is likely the result of lost connection. For this case the failure is best handled in the NSURLConnection's delegate. When downloading the image if - (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error is called then the data for the request should be discarded.
Also keep in mind that didFailWithError: will not be called for 4xx or 5xx responses from the server. It is called when the connection is cut off for other reasons. It would generally be a good idea to make sure you only write image data to disk when the server has responded with a 200 OK.

Is there a way to use a random project png image for a UITableViewCell?

I am populating a standard UITableViewCell with an image as follows:
cell.imageView.image = [UIImage imageNamed:#"someImageName.png"];
Is there a way to have "someImageName.png" be a random png image within my Xcode project? For the record, what I'd really like to do is put similar images in their own directory within the project - e.g. pets, faces, etc, and then depending on the table row select a random image from that directory.
I know I could rename the images using a scheme such as "image_0.png", "image_1.png" ... "image_n.png" and then use a random number x between 0..n to create "image_x.png" - but I'm curious if there's a way just to retrieve a random .png image file without doing the renaming (or writing the files to local storage, then retrieving a random file from there)?
Thanks very much.
You'll need to use the - (NSArray *)pathsForResourcesOfType:(NSString *)extension inDirectory:(NSString *)subpath; method of NSBundle class.
Then just take one random path from that array and get the image with +(UIImage*)imageWithContentsOfFile::(NSString*)fileName; or +(UIImage*)imageWithData:(NSData*)imageData; and the +(NSData*)dataWithContentsOfURL:(NSURL *)url;

Change file names of images?

I want to change the file names of images in my app, can i do this?
If the image is inside your NSBundle, then the answer is No. If you copy an image from ALAssetsLibrary you can name it whatever you like.
If it is in your NSBundle and you'd like to create a copy of the same image name, you can do that by loading the NSData and saving it with a different name. That just uses up extra space though.
Why are you trying to change the name of an image to begin with? If you needed to, you can create an NSMutableDictionary and a special function which takes a "filename" and returns the name of the actual image file in your NSBundle.
For example if you had a file named "MyImage.png" which part of your program thinks is actually called "ThatCoolPicture.png", you can load it like this:
UIImage *img = [UIImage imageNamed:[self nameForPseudoname:#"ThatCoolPicture.png"]];
In this case nameForPseudoname takes a "nickname" and returns the real name.
Hope this helps!