Take the 2-minute tour ×

I'm making an applications that let users take a photo and show them both in thumbnail and photo viewer. I have NSManagedObject class called photo and photo has a method that takes UIImage and converts it to PNG using UIImagePNGRepresentation() and saves it to filesystem. After this operation, resize the image to thumbnail size and save it.

The problem here is UIImagePNGRepresentation() and conversion of image size seems to be really slow and I don't know if this is a right way to do it.

Tell me if anyone know the best way to accomplish what I want to do.

Thank you in advance.

share|improve this question

4 Answers 4

Yes, it does take time on iPhone 4, where the image size is around 6 MB. The solution is to execute UIImagePNGRepresentation() in a background thread, using performSelectorInBackground:withObject:, so that your UI thread does not freeze.

share|improve this answer
I'm using GCD so there is no freezing. My problem is if the user immediately access to the photo, it does not read because the photo conversion/writing is still in process. –  kazuochi Oct 4 '11 at 18:09
@kazuhito0000 Take a look at my answer below. If you use GCD in combination with a completion block, it becomes easy. stackoverflow.com/a/13279514/257550 –  Michael G. Emmons Nov 7 '12 at 22:58

Depending on the image resolution, UIImagePNGRepresentation can indeed be quite slow, as can any writing to the file system.

You should always execute these types of operations in an asynchronous queue. Even if the performance seems good enough for your application when testing, you should still do it an asynch queue -- you never know what other processes the device might have going on which might slow the save down once your app is in the hands of users.

Newer versions of iOS make saving asynchronously really, really easy using Grand Central Dispatch (GCD). The steps are:

  1. Create an NSBlockOperation which saves the image
  2. In the block operation's completion block, read the image from disk & display it. The only caveat here is that you must use the main queue to display the image: all UI operations must occur on the main thread.
  3. Add the block operation to an operation queue and watch it go!

That's it. And here's the code:

// Create a block operation with our saves
NSBlockOperation* saveOp = [NSBlockOperation blockOperationWithBlock: ^{

   [UIImagePNGRepresentation(image) writeToFile:file atomically:YES];
   [UIImagePNGRepresentation(thumbImage) writeToFile:thumbfile atomically:YES];


// Use the completion block to update our UI from the main queue
[saveOp setCompletionBlock:^{

   [[NSOperationQueue mainQueue] addOperationWithBlock:^{ 

      UIImage *image = [UIImage imageWithContentsOfFile:thumbfile];
      // TODO: Assign image to imageview


// Kick off the operation, sit back, and relax. Go answer some stackoverflow
// questions or something.
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[queue addOperation:saveOp];

Once you are comfortable with this code pattern, you will find yourself using it a lot. It's incredibly useful when generating large datasets, long operations on load, etc. Essentially, any operation that makes your UI laggy in the least is a good candidate for this code. Just remember, you can't do anything to the UI while you aren't in the main queue and everything else is cake.

share|improve this answer
OP has already stated that his is performing the operation in the background using GCD. This is not the issue. –  Robin Summerhill Nov 7 '12 at 23:41
His original post makes no mention of GCD. He does make a comment that he tried it based on a different answer and he still couldn't get it to work because of the async nature of the operation. This post addresses both issues. No need to take a -1 mod personally. Your answer was wrong. This one is correct. –  Michael G. Emmons Nov 8 '12 at 19:47

It will probably be much faster to do the resizing before converting to PNG.

share|improve this answer
But then I have to convert both original and thumbnail version to PNG,right? –  kazuochi Oct 4 '11 at 18:06
Oh, didn't realize you needed both the original and thumbnail. –  Icydog Oct 5 '11 at 14:55
Resizing before or after converting makes no difference whatsoever. –  Michael G. Emmons Nov 7 '12 at 22:56

Try UIImageJPEGRepresentation with a medium compression quality. If the bottleneck is IO then this may prove faster as the filesize will generally be smaller than a png.

Use Instruments to check whether UIImagePNGRepresentation is the slow part or whether it is writing the data out to the filesystem which is slow.

share|improve this answer
I thought about converting jpeg, but I prefer PNG.. If writing data is slow part do you know how to make it faster? –  kazuochi Oct 4 '11 at 18:11
You will have to accept the performance hit then. –  Robin Summerhill Oct 4 '11 at 18:12
You absolutely do not have to accept the performance hit. This is the type of thing you should do in the background so it doesn't affect your UI or other pending operations. –  Michael G. Emmons Nov 7 '12 at 22:55
kazuhito0000 has already stated that he is performing this operation using GCD in the background and the problem is not that his UI is freezing. His problem is occurs when the user tries to immediately access the photo while it is still converting in the background. My advice stands - use profiling to work out why this process is taking too long and address the issue based on that. –  Robin Summerhill Nov 7 '12 at 23:38
He states no such thing in the original post. There is no mention of GCD. My answer addresses both his original question and his problem applying GCD as a solution -- it results in no UI hang. Your solution is completely irrelevant, which is why I marked it down. It addresses the symptom rather than the cause. Decreasing how much data you write to IO does not solve the problem that IO is a blocking operation, it simply makes it less noticeable. –  Michael G. Emmons Nov 8 '12 at 19:55

Your Answer


