When should I use UIImageJPEGRepresentation and UIImagePNGRepresentation for uploading different image formats to the server?

26,171

Solution 1

You say:

Of course it's obvious that for .png images I need to use UIImagePNGRepresentation and for .jpg/.jpeg UIImageJPEGRepresentation.

No, that's not necessarily the case. If you have some original "digital asset", rather than creating a UIImage and then using one of those two functions to create the NSData that you'll upload, you will often just load the NSData from the original asset and bypass the round-trip to a UIImage at all. If you do this, you don't risk any loss of data that converting to a UIImage, and then back again, can cause.

There are some additional considerations, though:

  1. Meta data:

    These UIImageXXXRepresentation functions strip the image of its meta data. Sometimes that's a good thing (e.g. you don't want to upload photos of your children or expensive gadgets the include the GPS locations where malcontents could identify where the shot was taken). In other cases, you don't want the meta data to be thrown away (e.g. date of the original shot, which camera, etc.).

    You should make an explicit decision as to whether you want meta data stripped or not. If not, don't round-trip your image through a UIImage, but rather use the original asset.

  2. Image quality loss and/or file size considerations:

    I'm particularly not crazy about UIImageJPEGRepresentation because it a lossy compression. Thus, if you use a compressionQuality value smaller than 1.0, you can lose some image quality (modest quality loss for values close to 1.0, more significant quality loss with lower compressionQuality values). And if you use a compressionQuality of 1.0, you mitigate much of the JPEG image quality loss, but the resulting NSData can often be bigger than the original asset (at least if the original was, itself, a compressed JPEG or PNG), resulting in slower uploads.

    UIImagePNGRepresentation doesn't introduce compression-based data loss, but depending upon the image, you may still lose data (e.g. if the original file was a 48-bit TIFF or used a colorspace other than sRGB).

    It's a question of whether you are ok with some image quality loss and/or larger file size during the upload process.

  3. Image size:

    Sometimes you don't want to upload the full resolution image. For example, you might be using a web service that wants images no bigger than 800px per side. Or if you're uploading a thumbnail, they might want something even smaller (e.g. 32px x 32px). By resizing images, you can make the upload much smaller and thus much faster (though with obvious quality loss). But if you use an image resizing algorithm, then creating a PNG or JPEG using these UIImageXXXRepresentation functions would be quite common.

In short, if I'm trying to minimize the data/quality loss, I would upload the original asset if it's in a format that the server accepts, and I'd use UIImagePNGRepresentation (or UIImageJPGRepresentation with quality setting of 1.0) if the original asset was not in a format accepted by the server. But the choice of using these UIImageXXXRepresentation functions is a question of your business requirements and what the server accepts.

Solution 2

Rob points out a lot of very good things to consider when working with images (+1), however here is an example of how to create tiff's and gif's as you asked:

First, you need to link to the ImageIO library (under the Build Phases of your app).

Next you need to #import <ImageIO/ImageIO.h> at the top of your file.

Then, the following code will convert the image for you:

// Get a reference to the image that you already have stored on disk somehow.
// If it isn't stored on disk, then you can use CGImageSourceCreateWithData() to create it from an NSData representation of your image.
NSURL *url = [[NSBundle mainBundle] URLForResource:@"01" withExtension:@"jpg"];
CGImageSourceRef src = CGImageSourceCreateWithURL((__bridge CFURLRef)(url), NULL);

// Create a URL referencing the Application Support Directory.  We will save the new image there.
NSFileManager *fm = [NSFileManager defaultManager];
NSURL *suppurl = [fm URLForDirectory:NSApplicationSupportDirectory
                            inDomain:NSUserDomainMask
                   appropriateForURL:nil
                              create:YES
                               error:NULL];

// Append the name of the output file to the app support directory
// For tiff change the extension in the next line to .tiff
NSURL *gifURL = [suppurl URLByAppendingPathComponent:@"mytiff.gif"];

// Create the destination for the new image
// For tiff, use @"public.tiff" for the second argument of the next line (instead of @com.compuserve.gif".
CGImageDestinationRef dest = CGImageDestinationCreateWithURL((__bridge CFURLRef)gifURL,
                                                             (CFStringRef)@"com.compuserve.gif",
                                                             1,
                                                             NULL);
CGImageDestinationAddImageFromSource(dest, src, 0, NULL);

// Write the image data to the URL.
bool ok = CGImageDestinationFinalize(dest);
if (!ok)
    NSLog(@"Unable to create gif file.");

// Cleanup
CFRelease(src);
CFRelease(dest);

This was adapted from the code in this book.

Share:
26,171
Oleksandr Karaberov
Author by

Oleksandr Karaberov

Updated on July 20, 2022

Comments

  • Oleksandr Karaberov
    Oleksandr Karaberov almost 2 years

    In my application I have to send images of different formats to the server (it must be all file formats that can be read by the UIImage class) https://developer.apple.com/library/ios/#documentation/uikit/reference/UIImage_Class/Reference/Reference.html

    And the problem is: I don't know when I should use each of this methods. Of course it's obvious that for .png images I need to use UIImagePNGRepresentation and for .jpg/.jpeg UIImageJPEGRepresentation. But what about other formats (.tiff,.gif , etc.)? There are only two methods for image manipulations and so many formats.