8

I want to be able to, being given a path to an image, convert that image into another image, but with a different format. By format I mean .png, .bmp .jpg .tiff, etc. In pseudocode, this is really easy:

image = [ImageAPI open: imagePath]
[image save: imagePath withFormat: IMAGEFORMAT] // this is important

I have no idea how to do this, though. I barely know more than the NSImage class when it comes to handling images), and that does not seem to have the answer to my problem (no simple save methods like this). Here is the list of formats I'd like to support:

  • .png
  • .tiff
  • .gif
  • .jpeg
  • .bmp
  • PROBABLY .pdf (if it isn't very complicated)

By support I mean opening any of those and saving the opened image into any of those formats. There are some combinations here (15 ??? - I think), so I could write a method for each combination like so:

[self saveTiffImageIntoGifWithPath: path] (*15 !!!)

But it is defenitely better to use APIs.

If by any chance along the way I also have options like:

  • keep alpha or not
  • resize images

...I'd be happy to support them as well, although they're optional. I really hope there's a simple way to do this. THANKS

PS: I know there have been questions about this topic, but they were all iPhone oriented (I want to do this on the mac) and none of them provided a way to do this with multiple formats.

Alex
  • 5,009
  • 3
  • 39
  • 73

2 Answers2

11

Allright, so with Peter's help I could figure this out. First, if you're working with image paths, then open directly the file with NSData like so:

NSData* imgData = [NSData dataWithContentsOfFile: filePath];

If you're working with NSImage objects and is difficult for you to have the path (for example with an NSImageView) then do this (image is the NSImage object you have):

NSData* imgData = [image TIFFRepresentation];

Now that you have your image into NSData objects, get it into a NSBitmapImageRep:

NSBitmapImageRep* bitmap = [NSBitmapImageRep imageRepWithData: imgData];

And then get a new NSData object, but with a different format:

NSData* newData = [bitmap representationUsingType: NSPNGFileType properties: nil];
// I used NSPNGFileType as an example, but all the
// types I wanted to convert between (except PDF) are supported

Finally, save that newData into a file:

[newData writeToFile: newPath atomically: YES]

Simple as pie, once you get how it works!


The support for transparency and size control is not that difficult either:

  • The NSImage class provides support for setting image's size (-setSize:)
  • The NSImageRep (superclass of NSBitmapImageRep) has the -setAlpha: method

Just call those when you need. +1 for Cocoa!

Alex
  • 5,009
  • 3
  • 39
  • 73
  • 1
    That's doing a lot of unnecessary work. You don't need to export the file to TIFF to export it as PNG. When you have a path to a file or data of the file's contents, it's one step to create an NSBitmapImageRep, and you can then create the PNG data directly from that. – Peter Hosey Jul 04 '11 at 21:22
  • 1
    @peter Yes, I know that. But imagine I'm working with NSImageView. It doesn't give you paths, only NSImage objects, so in that case you need to convert NSImage into NSData, and that's the only way I found how to do it. Otherwise, of course! Don't use NSImage, open with NSData just like you said. – Alex Jul 05 '11 at 09:40
  • Or directly from the file, when you have a path. If you ever had a path, why not keep it? You should not be storing your model in views; you pass it to the view only for the view to use. Your controller should hold onto the path to the original image the whole time. If this is a document-based application, it does that anyway; if not, you'll have to, and you should, do that yourself. – Peter Hosey Jul 05 '11 at 09:59
2

Exploring outward from NSImage leads you to NSBitmapImageRep, which does exactly what you want.

Some of those iPhone questions are relevant as well, because the solution that works on both platforms (and the implementation behind the NSBitmapImageRep solution nowadays) is to use CGImageSource to read in the image and CGImageDestination to write it out.

Peter Hosey
  • 95,783
  • 15
  • 211
  • 370
  • Allright, NSBitmapImageRep seems to do the conversion (`representationUsingType:properties:`), but I realy don't understand how to save the image then! I load the image with NSImage, add a representation using `[NSBitmapImageRep representationUsingType:properties:]` and then what?!? There's no save method like `saveImageToPath`. I must be missing something completely obvious... – Alex Jul 04 '11 at 10:51
  • Oh... I think I got it this time. Please check this: I open the original image using NSData, pass the data into `[NSBitmapImageRep initWithData:]`, call `[NSBitmapImageRep representationUsingType:properties:]`, then write the resulting data to a file. Voila! Is this it? It better be, or I'll get really confused. I can't test it right now, so that's why I'm asking. PS: If this is it, then the solution really was obvious... :) – Alex Jul 04 '11 at 11:00
  • @Alex Truppel: Yup, although NSBitmapImageRep does let you create one directly from the contents of a file. (Don't forget to look in superclasses!) – Peter Hosey Jul 04 '11 at 21:20