Go Back   MacRumors Forums > Apple Systems and Services > Programming > Mac Programming

Reply
 
Thread Tools Search this Thread Display Modes
Old Oct 26, 2009, 09:42 AM   #1
lodevalm
macrumors newbie
 
Join Date: Oct 2009
Location: Torino, Italy
Cocoa/Objective-C: crop and save an image

Hello,

I'm a Java/PHP programmer, and I've started programming in Objective-C for Mac OSX.

I've understood the MVC pattern for programming user interfaces with Cocoa, but I'm very confused about the SDK to manage filesystem, images, and so on...

I've a quite stupid problem but I cannot find an easy solution.

What I need is:
1. Load an image from a file
2. Check the size (width and height) and do some stuffs...
3. Crop this image in squares
4. Save each square in a new image file (PNG).

I cannot understand how to achieve point 3 and what kind of object I have to use, NSImage? CIImage? CGImage?

Any suggestment will be appreciated.
Thanks a lot.

Last edited by lodevalm; Oct 26, 2009 at 10:00 AM.
lodevalm is offline   0 Reply With Quote
Old Oct 26, 2009, 10:59 AM   #2
robbieduncan
Moderator
 
robbieduncan's Avatar
 
Join Date: Jul 2002
Location: London
NSImage will probably work fine. Pseudo-code for what you want to do is:

1) Create a new NSImage of the size you want the output to be
2) Lock focus for drawing on that image
3) Draw the image you want crop into the new image
4) Unlock focus
5) Save the PNG representation.

Docs are:

1) initWithSize:
2) lockFocus
3) drawInRect:fromRectperation:fraction:
4) unlockFocus

5) is a bit more complex. I would suggest that you can use addRepresentation: and add a NSBitmapImageRep (or check if there is one first). Once you have an NSImageBitmapRep you can use representationUsingTyperoperties: with NSPNGFileType and nil properties to get PNG data to write to a file.
robbieduncan is offline   0 Reply With Quote
Old Oct 27, 2009, 07:51 AM   #3
lodevalm
Thread Starter
macrumors newbie
 
Join Date: Oct 2009
Location: Torino, Italy
Thanx Robbie,

your help put me in the right way :-)
so, here is the first version of the code:

Code:
	NSImage *source = [[NSImage alloc]initWithContentsOfFile:@"/Users/daniele/Pictures/lda/lodevalm01.jpg"];
	NSImage *target = [[NSImage alloc]initWithSize:NSMakeSize(128,128)];
	
	[target lockFocus];
	[source drawInRect:NSMakeRect(0,0,128,128) 
		fromRect:NSMakeRect(0,0,128,128) 
		operation:NSCompositeCopy
		fraction:1.0];
	[target unlockFocus];
	
	NSBitmapImageRep *bits = [[target representations] objectAtIndex: 0];

	NSData *data = [bits representationUsingType: NSPNGFileType
		properties: nil];
	[data writeToFile: @"/Users/daniele/Pictures/lda/lodevalm01_crop.png"
		atomically: NO];

I'm not sure, because I cannot understand exactly the messages from the debugger, but I've got an error calling representationUsingType, the message is:

Uncaught exception: <NSInvalidArgumentException> *** -[NSCachedImageRep representationUsingTyperoperties:]: selector not recognized [self = 0x312b80]

Could you please help me again in understand this part?

Just in case, as additional info, I'm using version 2.5 of XCode.

(Sorry for the english, I hope it's clear...)

Thanks again!
lodevalm is offline   0 Reply With Quote
Old Oct 27, 2009, 08:52 AM   #4
robbieduncan
Moderator
 
robbieduncan's Avatar
 
Join Date: Jul 2002
Location: London
You have made an unsafe assumption. You assume that the first representation is an NSBitmapImageRep. This may or may not be the case. In your case it is not: it's an NSCachedImageRep. You need to iterate through the representations until you find an NSBitmapImageRep. If you don't find one create one and add it to the NSImage.
robbieduncan is offline   0 Reply With Quote
Old Oct 27, 2009, 10:53 AM   #5
lodevalm
Thread Starter
macrumors newbie
 
Join Date: Oct 2009
Location: Torino, Italy
Ok, now I did it :-)

This code works!

I've created a NSBitmapImageRep and added it to the target representations.

Code:
//Get the source image from file
	NSImage *source = [[NSImage alloc]initWithContentsOfFile:@"/Users/daniele/Pictures/lda/lodevalm02.jpg"];
	
	//Init target image
	NSImage *target = [[NSImage alloc]initWithSize:NSMakeSize(128,128)];
	
	//start drawing on target
	[target lockFocus];
	//draw the portion of the source image on target image
	[source drawInRect:NSMakeRect(0,0,128,128) 
		fromRect:NSMakeRect(0,0,128,128) 
		operation:NSCompositeCopy
		fraction:1.0];
	//end drawing
	[target unlockFocus];
	
	//create a NSBitmapImageRep
	NSBitmapImageRep *bmpImageRep = [[NSBitmapImageRep alloc]initWithData:[target TIFFRepresentation]];
	//add the NSBitmapImage to the representation list of the target
	[target addRepresentation:bmpImageRep];
	
	//get the data from the representation
	NSData *data = [bmpImageRep representationUsingType: NSPNGFileType
		properties: nil];
		
	//write the data to a file
	[data writeToFile: @"/Users/daniele/Pictures/lda/lodevalm01_crop.png"
		atomically: NO];
Just one more question:
This code will be a function in a utility class, so, after doing this stuffs, I need to release every object I used?
In this case the source and target image, because other objects are pointers. Is it correct?

Thanks, again!!!
lodevalm is offline   0 Reply With Quote
Old Oct 27, 2009, 11:11 AM   #6
lee1210
macrumors 68040
 
lee1210's Avatar
 
Join Date: Jan 2005
Location: Dallas, TX
Quote:
Originally Posted by lodevalm View Post
Just one more question:
This code will be a function in a utility class, so, after doing this stuffs, I need to release every object I used?
In this case the source and target image, because other objects are pointers. Is it correct?

Thanks, again!!!
Is the "end product" just the file on disk? Do you want any object that you generated available in-memory any more, or are you done with them? If you are done with them, you need to send a release to anything that you got back from a call with alloc or new in it. This means:
source
target
bmpImageRep

data should be autoreleased since representationUsingType does not contain the words alloc or new, so it should get release sent to it the next time an autorelease pool is released. If you're calling this method a lot in a loop, you may want to set up a new autorelease pool around the loop and release it afterwards so all of these things will get released immediately.

If you have not already, read:
http://developer.apple.com/mac/libra...emoryMgmt.html

-Lee
lee1210 is offline   0 Reply With Quote
Old Nov 3, 2009, 10:23 AM   #7
lodevalm
Thread Starter
macrumors newbie
 
Join Date: Oct 2009
Location: Torino, Italy
Thanks Lee,

at the moment, the app only do the crop task as helper in a project, I have no time to go deeper in memory management, so, it works with your suggests...and it's enough! :-)

Inside a for loop I alloc an NSImage (the cropped image), I use it with the NSBitmapImageRep and then I dispose those two objects.
After the loop I dispose the target image.
lodevalm is offline   0 Reply With Quote

Reply
MacRumors Forums > Apple Systems and Services > Programming > Mac Programming

Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Similar Threads
thread Thread Starter Forum Replies Last Post
Cocoa Touch and Objective C phalgun27 iPhone/iPad Programming 7 Aug 1, 2013 08:09 PM
Basic Objective-C Cocoa questions? cpuin Mac Programming 8 Jun 3, 2013 08:10 PM
Can I make Objective-C/Cocoa command-line text-mode applications? printz Mac Programming 3 May 2, 2013 09:01 PM
BecomeAnXcoder : A free book for starting with Cocoa using Objective-C msaljaber iPhone/iPad Programming 0 Feb 7, 2013 06:30 AM
WebView in Cocoa (Objective-C) tr!pf!3 Mac Programming 0 Aug 28, 2012 10:48 AM

Forum Jump

All times are GMT -5. The time now is 01:42 AM.

Mac Rumors | Mac | iPhone | iPhone Game Reviews | iPhone Apps

Mobile Version | Fixed | Fluid | Fluid HD
Copyright 2002-2013, MacRumors.com, LLC