adium 3782:e660e9081fb6: Added ability to resize animated gifs t...

commits at adium.im commits at adium.im
Sun Mar 27 02:19:10 UTC 2011


details:	http://hg.adium.im/adium/rev/e660e9081fb6
revision:	3782:e660e9081fb6
branch:		10.6+
author:		Adrian Godoroja <robotive at me.com>
date:		Wed Mar 23 21:30:28 2011 +0200

Added ability to resize animated gifs that are too large. refs #9885
Most gif's are still to large after resize, so a still image will be sent to the server.
!Feedback is highly wanted on this feature.
This page: http://adium.im/help/pgs/Accounts-BuddyIcons.html will need an update when 1.5 is out.
Subject: adium 3783:fd7808a9f165: Removed a duplicate reference to Sparkle.framework

details:	http://hg.adium.im/adium/rev/fd7808a9f165
revision:	3783:fd7808a9f165
branch:		10.6+
author:		Adrian Godoroja <robotive at me.com>
date:		Sat Mar 26 23:23:55 2011 +0200

Removed a duplicate reference to Sparkle.framework
Updated a bunch of adiumx.com URL to adium.im

diffs (truncated from 3702 to 1000 lines):

diff -r 5721d368ee1b -r fd7808a9f165 Adium.xcodeproj/project.pbxproj
--- a/Adium.xcodeproj/project.pbxproj	Mon Mar 21 07:20:32 2011 -0700
+++ b/Adium.xcodeproj/project.pbxproj	Sat Mar 26 23:23:55 2011 +0200
@@ -1467,7 +1467,6 @@
 		811036260CDE8C2100EC6038 /* adiumPurpleCertificateTrustWarning.m in Sources */ = {isa = PBXBuildFile; fileRef = 811036240CDE8C2100EC6038 /* adiumPurpleCertificateTrustWarning.m */; };
 		8110362C0CDE8F5800EC6038 /* AIPurpleCertificateTrustWarningAlert.h in Headers */ = {isa = PBXBuildFile; fileRef = 8110362A0CDE8F5800EC6038 /* AIPurpleCertificateTrustWarningAlert.h */; };
 		8110362D0CDE8F5800EC6038 /* AIPurpleCertificateTrustWarningAlert.m in Sources */ = {isa = PBXBuildFile; fileRef = 8110362B0CDE8F5800EC6038 /* AIPurpleCertificateTrustWarningAlert.m */; };
-		8163F99C0B318824002005EE /* Sparkle.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 638392F609D4D67A0067B9B7 /* Sparkle.framework */; };
 		8173C5760C4C3DB800C9E64E /* downloadprogress.png in Resources */ = {isa = PBXBuildFile; fileRef = 8173C5750C4C3DB800C9E64E /* downloadprogress.png */; };
 		8181EEBE0C30673E00E802F7 /* AMPurpleSearchResultsWindow.nib in Resources */ = {isa = PBXBuildFile; fileRef = 8181EEBD0C30673E00E802F7 /* AMPurpleSearchResultsWindow.nib */; };
 		8181EEC30C3067B500E802F7 /* AMPurpleSearchResultsController.h in Headers */ = {isa = PBXBuildFile; fileRef = 8181EEC10C3067B500E802F7 /* AMPurpleSearchResultsController.h */; };
@@ -1488,7 +1487,6 @@
 		81DAED520C26F4F700780E4C /* AMPurpleJabberServiceDiscoveryBrowsing.h in Headers */ = {isa = PBXBuildFile; fileRef = 81DAED500C26F4F700780E4C /* AMPurpleJabberServiceDiscoveryBrowsing.h */; };
 		81DAED530C26F4F700780E4C /* AMPurpleJabberServiceDiscoveryBrowsing.m in Sources */ = {isa = PBXBuildFile; fileRef = 81DAED510C26F4F700780E4C /* AMPurpleJabberServiceDiscoveryBrowsing.m */; };
 		81E45D760C15BFF800B7381B /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 34E839050583207E00F2AADB /* SystemConfiguration.framework */; };
-		9722ABC613257D5800CAB486 /* ContactListWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = 9722ABC513257D5800CAB486 /* ContactListWindow.xib */; };
 		9722ABC813257D7F00CAB486 /* ContactListWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = 9722ABC713257D7F00CAB486 /* ContactListWindow.xib */; };
 		97AF5CDB13191DE200550C41 /* AIContactListUserPictureMenuController.m in Sources */ = {isa = PBXBuildFile; fileRef = 97AF5CDA13191DE200550C41 /* AIContactListUserPictureMenuController.m */; };
 		97AF5CE713191E4800550C41 /* AIImageCollectionView.h in Headers */ = {isa = PBXBuildFile; fileRef = 97AF5CE213191E2800550C41 /* AIImageCollectionView.h */; settings = {ATTRIBUTES = (Public, ); }; };
@@ -1831,7 +1829,7 @@
 		0C27C8640C75A23A002AA363 /* NSStringScriptingAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = NSStringScriptingAdditions.m; path = Source/NSStringScriptingAdditions.m; sourceTree = "<group>"; };
 		0C79A2D60C5E633F005AE6FA /* AIMoveCommand.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AIMoveCommand.h; path = Source/AIMoveCommand.h; sourceTree = "<group>"; };
 		0C79A2D70C5E633F005AE6FA /* AIMoveCommand.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AIMoveCommand.m; path = Source/AIMoveCommand.m; sourceTree = "<group>"; };
-		0CAC6A130C0C657A0090AE95 /* Adium.sdef */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.sdef; name = Adium.sdef; path = Resources/Adium.sdef; sourceTree = "<group>"; };
+		0CAC6A130C0C657A0090AE95 /* Adium.sdef */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.xml; name = Adium.sdef; path = Resources/Adium.sdef; sourceTree = "<group>"; };
 		0CD3C3AA0C43C8CC003E637C /* NSWindowScriptingAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NSWindowScriptingAdditions.h; path = Source/NSWindowScriptingAdditions.h; sourceTree = "<group>"; };
 		0CD3C3AB0C43C8CC003E637C /* NSWindowScriptingAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = NSWindowScriptingAdditions.m; path = Source/NSWindowScriptingAdditions.m; sourceTree = "<group>"; };
 		0CD41C6E0C2776540082F83B /* AICreateCommand.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AICreateCommand.h; path = Source/AICreateCommand.h; sourceTree = "<group>"; };
@@ -4732,7 +4730,6 @@
 		81DAE8710C261E8A00780E4C /* AMPurpleTuneTooltip.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AMPurpleTuneTooltip.m; path = "Plugins/Purple Service/AMPurpleTuneTooltip.m"; sourceTree = "<group>"; };
 		81DAED500C26F4F700780E4C /* AMPurpleJabberServiceDiscoveryBrowsing.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AMPurpleJabberServiceDiscoveryBrowsing.h; path = "Plugins/Purple Service/AMPurpleJabberServiceDiscoveryBrowsing.h"; sourceTree = "<group>"; };
 		81DAED510C26F4F700780E4C /* AMPurpleJabberServiceDiscoveryBrowsing.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AMPurpleJabberServiceDiscoveryBrowsing.m; path = "Plugins/Purple Service/AMPurpleJabberServiceDiscoveryBrowsing.m"; sourceTree = "<group>"; };
-		9722ABC513257D5800CAB486 /* ContactListWindow.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = ContactListWindow.xib; path = Resources/ContactListWindow.xib; sourceTree = "<group>"; };
 		9722ABC713257D7F00CAB486 /* ContactListWindow.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = ContactListWindow.xib; path = Resources/ContactListWindow.xib; sourceTree = "<group>"; };
 		97AF5CD913191DE200550C41 /* AIContactListUserPictureMenuController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AIContactListUserPictureMenuController.h; path = Source/AIContactListUserPictureMenuController.h; sourceTree = "<group>"; };
 		97AF5CDA13191DE200550C41 /* AIContactListUserPictureMenuController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AIContactListUserPictureMenuController.m; path = Source/AIContactListUserPictureMenuController.m; sourceTree = "<group>"; };
@@ -4948,7 +4945,6 @@
 				638392F809D4D67A0067B9B7 /* Sparkle.framework in Frameworks */,
 				9E1E1DFD0A96741500E16DFC /* LMX.framework in Frameworks */,
 				377EC8940AE9525B00CB7BDF /* PSMTabBarControl.framework in Frameworks */,
-				8163F99C0B318824002005EE /* Sparkle.framework in Frameworks */,
 				11AA1EFA0BCAE9C3003DDA66 /* Quartz.framework in Frameworks */,
 				340C1ABF0BD58FAB00D09235 /* Security.framework in Frameworks */,
 				31E0CD810C5EEF5200271DB1 /* CoreAudio.framework in Frameworks */,
@@ -5265,7 +5261,6 @@
 				29B97323FDCFA39411CA2CEA /* Linked Frameworks */,
 				63C7E0280FAF9B7D00B310AC /* xcconfigs */,
 				19C28FACFE9D520D11CA2CBB /* Products */,
-				9722ABC513257D5800CAB486 /* ContactListWindow.xib */,
 			);
 			name = CocAIMe2;
 			sourceTree = "<group>";
@@ -10019,7 +10014,6 @@
 				76889DEF12D3CA40007AEF00 /* Personal.png in Resources */,
 				1154F50A12E1476900B8CA27 /* AILogByAccountWindow.nib in Resources */,
 				97AF5CF413191E9A00550C41 /* ContactListChangeUserPictureMenu.xib in Resources */,
-				9722ABC613257D5800CAB486 /* ContactListWindow.xib in Resources */,
 				9722ABC813257D7F00CAB486 /* ContactListWindow.xib in Resources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
diff -r 5721d368ee1b -r fd7808a9f165 ChangeLogs/Changes.txt
--- a/ChangeLogs/Changes.txt	Mon Mar 21 07:20:32 2011 -0700
+++ b/ChangeLogs/Changes.txt	Sat Mar 26 23:23:55 2011 +0200
@@ -40,6 +40,9 @@
  Transcript Viewer
  * Added next/previous buttons for highlighted search terms within a transcript (similar to Safari).
 
+ User Picture (Buddy Icons)
+ * Ability to resize animated gifs that are too large (#9885)
+
  AIM
   * Added a preference for AIM: "allow multiple sign in locations" defaulting to true. (Josh Perry) (#5790)
 
diff -r 5721d368ee1b -r fd7808a9f165 Frameworks/AIUtilities Framework/Source/AIImageAdditions.h
--- a/Frameworks/AIUtilities Framework/Source/AIImageAdditions.h	Mon Mar 21 07:20:32 2011 -0700
+++ b/Frameworks/AIUtilities Framework/Source/AIImageAdditions.h	Sat Mar 26 23:23:55 2011 +0200
@@ -32,6 +32,7 @@
     AIJPEG2000FileType = NSJPEG2000FileType
 } AIBitmapImageFileType;
 
+
 @interface NSImage (AIImageAdditions)
 
 + (NSImage *)imageNamed:(NSString *)name forClass:(Class)inClass;
@@ -59,10 +60,21 @@
 - (NSData *)PNGRepresentation;
 - (NSData *)GIFRepresentation;
 - (NSData *)BMPRepresentation;
+- (NSData *)bestRepresentationByType;
 - (NSBitmapImageRep *)largestBitmapImageRep;
 - (NSData *)representationWithFileType:(NSBitmapImageFileType)fileType
 					   maximumFileSize:(NSUInteger)maximumSize;
 
+/*
+ * Writes Application Extension Block and modifies Graphic Control Block for a GIF image
+ */
+- (void)writeGIFExtensionBlocksInData:(NSMutableData *)data forRepresenation:(NSBitmapImageRep *)bitmap;
+
+/*
+ * Properties for a GIF image
+ */
+- (NSDictionary *)GIFPropertiesForRepresentation:(NSBitmapImageRep *)bitmap;
+
 @end
 
 //Defined in AppKit.framework
diff -r 5721d368ee1b -r fd7808a9f165 Frameworks/AIUtilities Framework/Source/AIImageAdditions.m
--- a/Frameworks/AIUtilities Framework/Source/AIImageAdditions.m	Mon Mar 21 07:20:32 2011 -0700
+++ b/Frameworks/AIUtilities Framework/Source/AIImageAdditions.m	Sat Mar 26 23:23:55 2011 +0200
@@ -17,27 +17,31 @@
 #import "AIImageAdditions.h"
 
 @interface NSImage (AIImageAdditions_PRIVATE)
+
 - (NSBitmapImageRep *)bitmapRep;
+
 @end
 
 @implementation NSImage (AIImageAdditions)
 
 + (NSImage *)imageNamed:(NSString *)name forClass:(Class)inClass loadLazily:(BOOL)flag
 {
-	NSBundle	*ownerBundle;
-    NSString	*imagePath;
-    NSImage		*image;
+	NSBundle *ownerBundle;
+    NSString *imagePath;
+    NSImage	*image;
 	
-    //Get the bundle
+    // Get the bundle
     ownerBundle = [NSBundle bundleForClass:inClass];
 	
-    //Open the image
+    // Open the image
     imagePath = [ownerBundle pathForImageResource:name];   
-	if(flag)
+	
+	if(flag) {
 		image = [[NSImage alloc] initByReferencingFile:imagePath];
-	else
+	} else {
 		image = [[NSImage alloc] initWithContentsOfFile:imagePath];
-	
+	}
+
     return [image autorelease];	
 }
 
@@ -50,201 +54,26 @@
 + (NSImage *)imageForSSL
 {
 	static NSImage *SSLIcon = nil;
+	
 	if (!SSLIcon) {
 		NSBundle *securityInterfaceFramework = [NSBundle bundleWithIdentifier:@"com.apple.securityinterface"];
-		if (!securityInterfaceFramework) securityInterfaceFramework = [NSBundle bundleWithPath:@"/System/Library/Frameworks/SecurityInterface.framework"];
+		
+		if (!securityInterfaceFramework) {
+			securityInterfaceFramework = [NSBundle bundleWithPath:@"/System/Library/Frameworks/SecurityInterface.framework"];
+		}
 
 		SSLIcon = [[NSImage alloc] initByReferencingFile:[securityInterfaceFramework pathForImageResource:@"CertSmallStd"]];
 	}
+	
 	return SSLIcon;
 }
 
-//Create and return an opaque bitmap image rep, replacing transparency with [NSColor whiteColor]
-- (NSBitmapImageRep *)opaqueBitmapImageRep
-{
-	NSImage				*tempImage = nil;
-	NSBitmapImageRep	*imageRep = nil;
-	NSSize				size = [self size];
-	
-	//Work with a temporary image so we don't modify self
-	tempImage = [[[NSImage allocWithZone:[self zone]] initWithSize:size] autorelease];
-	
-	//Lock before drawing to the temporary image
-	[tempImage lockFocus];
-	
-	//Fill with a white background
-	[[NSColor whiteColor] set];
-	NSRectFill(NSMakeRect(0, 0, size.width, size.height));
-	
-	//Draw the image
-	[self compositeToPoint:NSZeroPoint operation:NSCompositeSourceOver];
-	
-	//We're done drawing
-	[tempImage unlockFocus];
-	
-	//Find an NSBitmapImageRep from the temporary image
-	for (NSImageRep *rep in tempImage.representations) {
-		if ([rep isKindOfClass:[NSBitmapImageRep class]]) {
-			imageRep = (NSBitmapImageRep *)rep;
-		}
-	}
-	
-	//Make one if necessary
-	if (!imageRep) {
-		imageRep = [NSBitmapImageRep imageRepWithData:[tempImage TIFFRepresentation]];
-    }
-	
-	// 10.6 behavior: Drawing into a new image copies the display's color profile in.
-	// Remove the color profile so we don't bloat the image size.
-	[imageRep setProperty:NSImageColorSyncProfileData withValue:nil];
-	
-	return imageRep;
-}
-
-- (NSBitmapImageRep *)largestBitmapImageRep
-{
-	//Find the biggest image
-	NSEnumerator *repsEnum = [[self representations] objectEnumerator];
-	NSBitmapImageRep *bestRep = nil;
-	NSImageRep *rep;
-	Class NSBitmapImageRepClass = [NSBitmapImageRep class];
-	CGFloat maxWidth = 0;
-	while ((rep = [repsEnum nextObject])) {
-		if ([rep isKindOfClass:NSBitmapImageRepClass]) {
-			CGFloat thisWidth = [rep size].width;
-			if (thisWidth >= maxWidth) {
-				//Cast explanation: GCC warns about us returning an NSImageRep here, presumably because it could be some other kind of NSImageRep if we don't check the class. Fortunately, we have such a check. This cast silences the warning.
-				bestRep = (NSBitmapImageRep *)rep;
-				maxWidth = thisWidth;
-			}
-		}
-	}
-	
-	//We don't already have one, so forge one from our TIFF representation.
-	if (!bestRep)
-		bestRep = [NSBitmapImageRep imageRepWithData:[self TIFFRepresentation]];
-	
-	return bestRep;
-}
-
-- (NSData *)JPEGRepresentation
-{	
-	return [self JPEGRepresentationWithCompressionFactor:1.0f];
-}
-
-- (NSData *)JPEGRepresentationWithCompressionFactor:(float)compressionFactor
-{
-	/* JPEG does not support transparency, but NSImage does. We need to create a non-transparent NSImage
-	* before creating our representation or transparent parts will become black.  White is preferable.
-	*/
-	return ([[self opaqueBitmapImageRep] representationUsingType:NSJPEGFileType 
-													  properties:[NSDictionary dictionaryWithObject:[NSNumber numberWithFloat:(float)compressionFactor] 
-																							 forKey:NSImageCompressionFactor]]);	
-}
-- (NSData *)JPEGRepresentationWithMaximumByteSize:(NSUInteger)maxByteSize
-{
-	/* JPEG does not support transparency, but NSImage does. We need to create a non-transparent NSImage
-	 * before creating our representation or transparent parts will become black.  White is preferable.
-	 */
-	NSBitmapImageRep *opaqueBitmapImageRep = [self opaqueBitmapImageRep];
-	NSData *data = nil;
-	for (float compressionFactor = 0.99f; compressionFactor > 0.4f; compressionFactor -= 0.01f) {
-		data = [opaqueBitmapImageRep representationUsingType:NSJPEGFileType 
-												  properties:[NSDictionary dictionaryWithObject:[NSNumber numberWithFloat:compressionFactor] 
-																						 forKey:NSImageCompressionFactor]];
-		if (data && ([data length] <= maxByteSize)) {
-			break;
-		} else {
-			data = nil;
-		}
-	}
-
-	return data;
-}
-
-- (NSData *)PNGRepresentation
-{
-	/* PNG is easy; it supports everything TIFF does, and NSImage's PNG support is great. */
-	NSBitmapImageRep	*bitmapRep =  [self largestBitmapImageRep];
-
-	return ([bitmapRep representationUsingType:NSPNGFileType properties:nil]);
-}
-
-- (NSData *)BMPRepresentation
-{
-	/* BMP does not support transparency, but NSImage does. We need to create a non-transparent NSImage
-	 * before creating our representation or transparent parts will become black.  White is preferable.
-	 */
-
-	return ([[self opaqueBitmapImageRep] representationUsingType:NSBMPFileType properties:nil]);
-}
-
-- (NSBitmapImageRep *)getBitmap
-{
-	[self lockFocus];
-	
-	NSSize size = [self size];
-	NSRect rect = NSMakeRect(0.0f, 0.0f, size.width, size.height);
-	NSBitmapImageRep	*bm = [[[NSBitmapImageRep alloc] initWithFocusedViewRect:rect] autorelease];
-	
-	[self unlockFocus];
-	
-	return bm;
-}
-
-//
-// NOTE: Black & White images fail miserably
-// So we must get their data and blast that into a deeper cache
-// Yucky, so we wrap this all up inside this object...
-- (NSBitmapImageRep *)bitmapRepForGIFRepresentation
-{
-	NSArray *reps = [self representations];
-	NSUInteger i = [reps count];
-	while (i--) {
-		NSBitmapImageRep *rep = (NSBitmapImageRep *)[reps objectAtIndex:i];
-		if ([rep isKindOfClass:[NSBitmapImageRep class]] &&
-			([rep bitsPerPixel] > 2))
-			return rep;
-	}
-	return [self getBitmap];
-}
-
-- (NSData *)GIFRepresentation
-{
-	//This produces ugly output.  Very ugly.
-
-	NSData	*GIFRepresentation = nil;
-	
-	NSBitmapImageRep *bm = [self bitmapRepForGIFRepresentation]; 
-	
-	if (bm) {
-		NSDictionary *properties =  [NSDictionary dictionaryWithObjectsAndKeys:
-			[NSNumber numberWithBool:YES], NSImageDitherTransparency,
-			nil];
-		
-		NSSize size = [self size];
-		
-		if (size.width > 0 && size.height > 0) {
-			
-			@try {
-				GIFRepresentation = [bm representationUsingType:NSGIFFileType
-													 properties:properties];
-			}
-			@catch(id exc) {
-				GIFRepresentation = nil;	// must have failed
-			}
-		}
-	}
-
-	return GIFRepresentation;
-}
-	
 + (AIBitmapImageFileType)fileTypeOfData:(NSData *)inData
 {
 	const char *data = [inData bytes];
 	NSUInteger len = [inData length];
 	AIBitmapImageFileType fileType = AIUnknownFileType;
-
+	
 	if (len >= 4) {
 		if (!strncmp((char *)data, "GIF8", 4))
 			fileType = AIGIFFileType;
@@ -265,6 +94,7 @@
 + (NSString *)extensionForBitmapImageFileType:(AIBitmapImageFileType)inFileType
 {
 	NSString *extension = nil;
+	
 	switch (inFileType) {
 		case AIUnknownFileType:
 			break;
@@ -291,6 +121,200 @@
 	return extension;
 }
 
+// Create and return an opaque bitmap image rep, replacing transparency with [NSColor whiteColor]
+- (NSBitmapImageRep *)opaqueBitmapImageRep
+{
+	NSImage				*tempImage = nil;
+	NSBitmapImageRep	*imageRep = nil;
+	NSSize				size = [self size];
+	
+	// Work with a temporary image so we don't modify self
+	tempImage = [[[NSImage allocWithZone:[self zone]] initWithSize:size] autorelease];
+	
+	// Lock before drawing to the temporary image
+	[tempImage lockFocus];
+	
+	// Fill with a white background
+	[[NSColor whiteColor] set];
+	NSRectFill(NSMakeRect(0, 0, size.width, size.height));
+	
+	// Draw the image
+	[self compositeToPoint:NSZeroPoint operation:NSCompositeSourceOver];
+	
+	// We're done drawing
+	[tempImage unlockFocus];
+	
+	// Find an NSBitmapImageRep from the temporary image
+	for (NSImageRep *rep in tempImage.representations) {
+		if ([rep isKindOfClass:[NSBitmapImageRep class]]) {
+			imageRep = (NSBitmapImageRep *)rep;
+		}
+	}
+	
+	// Make one if necessary
+	if (!imageRep) {
+		imageRep = [NSBitmapImageRep imageRepWithData:[tempImage TIFFRepresentation]];
+    }
+	
+	// 10.6 behavior: Drawing into a new image copies the display's color profile in.
+	// Remove the color profile so we don't bloat the image size.
+	[imageRep setProperty:NSImageColorSyncProfileData withValue:nil];
+	
+	return imageRep;
+}
+
+- (NSBitmapImageRep *)largestBitmapImageRep
+{
+	// Find the biggest image
+	NSBitmapImageRep *bestRep = nil;
+	Class NSBitmapImageRepClass = [NSBitmapImageRep class];
+	CGFloat maxWidth = 0.0f;
+	
+	for (NSImageRep *rep in [self representations]) {
+		if ([rep isKindOfClass:NSBitmapImageRepClass]) {
+			CGFloat thisWidth = [rep size].width;
+			
+			if (thisWidth >= maxWidth) {
+				// Cast explanation: GCC warns about us returning an NSImageRep here, presumably because it could be some other kind of NSImageRep if we don't check the class.
+				// Fortunately, we have such a check. This cast silences the warning.
+				bestRep = (NSBitmapImageRep *)rep;
+				maxWidth = thisWidth;
+			}
+		}
+	}
+	
+	// We don't already have one, so forge one from our TIFF representation.
+	if (!bestRep) {
+		bestRep = [NSBitmapImageRep imageRepWithData:[self TIFFRepresentation]];
+	}
+
+	return bestRep;
+}
+
+- (NSData *)JPEGRepresentation
+{	
+	return [self JPEGRepresentationWithCompressionFactor:1.0f];
+}
+
+- (NSData *)JPEGRepresentationWithCompressionFactor:(float)compressionFactor
+{
+	/* JPEG does not support transparency, but NSImage does. We need to create a non-transparent NSImage
+	 * before creating our representation or transparent parts will become black. White is preferable.
+	 */
+	return ([[self opaqueBitmapImageRep] representationUsingType:NSJPEGFileType 
+													  properties:[NSDictionary dictionaryWithObject:[NSNumber numberWithFloat:(float)compressionFactor] 
+																							 forKey:NSImageCompressionFactor]]);	
+}
+- (NSData *)JPEGRepresentationWithMaximumByteSize:(NSUInteger)maxByteSize
+{
+	/* JPEG does not support transparency, but NSImage does. We need to create a non-transparent NSImage
+	 * before creating our representation or transparent parts will become black. White is preferable.
+	 */
+	NSBitmapImageRep *opaqueBitmapImageRep = [self opaqueBitmapImageRep];
+	NSData *data = nil;
+	
+	for (float compressionFactor = 0.99f; compressionFactor > 0.4f; compressionFactor -= 0.01f) {
+		data = [opaqueBitmapImageRep representationUsingType:NSJPEGFileType 
+												  properties:[NSDictionary dictionaryWithObject:[NSNumber numberWithFloat:compressionFactor] 
+																						 forKey:NSImageCompressionFactor]];
+		if (data && ([data length] <= maxByteSize)) {
+			break;
+		} else {
+			data = nil;
+		}
+	}
+
+	return data;
+}
+
+- (NSData *)PNGRepresentation
+{
+	/* PNG is easy; it supports everything TIFF does, and NSImage's PNG support is great. */
+	NSBitmapImageRep *bitmapRep =  [self largestBitmapImageRep];
+
+	return ([bitmapRep representationUsingType:NSPNGFileType properties:nil]);
+}
+
+#warning 10.6+ only
+
+- (NSData *)GIFRepresentation
+{
+	// GIF requires special treatment, as Apple doesn't allow you to save animations.
+	
+	NSMutableData *GIFRepresentation = nil;
+	NSBitmapImageRep *bitmap = [[self representations] objectAtIndex:0];
+	
+	if (bitmap && [bitmap isKindOfClass:[NSBitmapImageRep class]]) {
+		unsigned frameCount = [[bitmap valueForProperty:NSImageFrameCount] intValue];
+		
+		if (!frameCount) {
+			frameCount = 1;
+		}
+		
+		NSSize size = [self size];
+		
+		if (size.width > 0 && size.height > 0) {
+			NSMutableArray *images = [NSMutableArray array];
+			
+			for (unsigned i = 0; i < frameCount; i++) {
+				// Set current frame
+				[bitmap setProperty:NSImageCurrentFrame withValue:[NSNumber numberWithUnsignedInt:i]];
+				// Add frame representation
+				[images addObject:[NSBitmapImageRep imageRepWithData:[bitmap representationUsingType:NSGIFFileType properties:nil]]];
+			}
+			
+			GIFRepresentation = [NSMutableData dataWithData:[NSBitmapImageRep representationOfImageRepsInArray:images
+																									 usingType:NSGIFFileType
+																									properties:[self GIFPropertiesForRepresentation:bitmap]]];
+			
+			// Write GIF Extension Blocks
+			[self writeGIFExtensionBlocksInData:GIFRepresentation forRepresenation:bitmap];
+		}
+	}
+	
+	return GIFRepresentation;
+}
+
+- (NSData *)BMPRepresentation
+{
+	/* BMP does not support transparency, but NSImage does. We need to create a non-transparent NSImage
+	 * before creating our representation or transparent parts will become black. White is preferable.
+	 */
+
+	return ([[self opaqueBitmapImageRep] representationUsingType:NSBMPFileType properties:nil]);
+}
+
+/*!
+ * @brief Returns a GIF representation for GIFs, and PNG represenation for all other types
+ */
+- (NSData *)bestRepresentationByType
+{
+	NSData *data = nil;
+	NSBitmapImageRep *bitmap = nil;
+	
+	if ((bitmap = [[self representations] objectAtIndex:0]) &&
+		[bitmap isKindOfClass:[NSBitmapImageRep class]] &&
+		([[bitmap valueForProperty:NSImageFrameCount] intValue] > 1)) {
+		data = [self GIFRepresentation];
+	} else {
+		data = [self PNGRepresentation];
+	}
+	
+	return data;
+}
+
+- (NSBitmapImageRep *)getBitmap
+{
+	[self lockFocus];
+	
+	NSSize size = [self size];
+	NSRect rect = NSMakeRect(0.0f, 0.0f, size.width, size.height);
+	NSBitmapImageRep *bm = [[[NSBitmapImageRep alloc] initWithFocusedViewRect:rect] autorelease];
+	
+	[self unlockFocus];
+	
+	return bm;
+}
 
 /*!
  * @brief Retrieve an image rep with a maximum size
@@ -302,8 +326,7 @@
  *
  * @return the NSData representation using fileType
  */
-- (NSData *)representationWithFileType:(NSBitmapImageFileType)fileType
-					   maximumFileSize:(NSUInteger)maximumSize
+- (NSData *)representationWithFileType:(NSBitmapImageFileType)fileType maximumFileSize:(NSUInteger)maximumSize
 {
 	NSBitmapImageRep *imageRep = [self largestBitmapImageRep];
 	
@@ -354,4 +377,56 @@
 	return data;
 }
 
+- (void)writeGIFExtensionBlocksInData:(NSMutableData *)data forRepresenation:(NSBitmapImageRep *)bitmap
+{
+	// GIF Application Extension Block - 0x21FF0B
+	const char *GIFApplicationExtensionBlock = "\x21\xFF\x0B\x4E\x45\x54\x53\x43\x41\x50\x45\x32\x2E\x30\x03\x01\x00\x00\x00";
+	// GIF Graphic Control Extension Block - 0x21F904
+	NSData *GIFGraphicControlExtensionBlock = [NSData dataWithBytes:"\x00\x21\xF9\x04" length:4];
+
+	NSRange blockRange;
+    NSUInteger blockLocation = [data length];
+	
+	unsigned frameCount = [[bitmap valueForProperty:NSImageFrameCount] intValue];
+	unsigned frameDuration;
+	unsigned i = 0;
+	
+	while (!NSEqualRanges(blockRange = [data rangeOfData:GIFGraphicControlExtensionBlock options:NSDataSearchBackwards range:NSMakeRange(0, blockLocation)], NSMakeRange(NSNotFound, 0))) {
+		// Set current frame
+		[bitmap setProperty:NSImageCurrentFrame withValue:[NSNumber numberWithUnsignedInt:i++]];
+
+		// Frame Duration flag, 1/100 sec
+		frameDuration = [[bitmap valueForProperty:NSImageCurrentFrameDuration] floatValue] * 100;
+
+        blockLocation = blockRange.location;
+		
+		// Replace bytes in Graphic Extension Block
+		[data replaceBytesInRange:NSMakeRange(NSMaxRange(blockRange) + 1, 2) withBytes:&frameDuration length:2];
+
+		// Write Application Extension Block
+		if (i == frameCount) {
+            [data replaceBytesInRange:NSMakeRange(blockRange.location + 1, 0) withBytes:GIFApplicationExtensionBlock length:strlen(GIFApplicationExtensionBlock) + 3];
+        }
+		
+		frameDuration = 0;
+    }
+}
+
+- (NSDictionary *)GIFPropertiesForRepresentation:(NSBitmapImageRep *)bitmap
+{
+	NSNumber *frameCount = [bitmap valueForProperty:NSImageFrameCount];
+
+	if (!frameCount) {
+		frameCount = [NSNumber numberWithUnsignedInt:1];
+	}
+
+	// Setting NSImageLoopCount & NSImageCurrentFrameDuration through - NSDictionary *properties - is not allowed!
+	return [NSDictionary dictionaryWithObjects:[NSArray arrayWithObjects:frameCount,
+																			[NSNumber numberWithUnsignedInt:0],
+																			nil]
+										forKeys:[NSArray arrayWithObjects:NSImageFrameCount,
+																			NSImageCurrentFrame,
+																			nil]];
+}
+
 @end
diff -r 5721d368ee1b -r fd7808a9f165 Frameworks/AIUtilities Framework/Source/AIImageDrawingAdditions.h
--- a/Frameworks/AIUtilities Framework/Source/AIImageDrawingAdditions.h	Mon Mar 21 07:20:32 2011 -0700
+++ b/Frameworks/AIUtilities Framework/Source/AIImageDrawingAdditions.h	Sat Mar 26 23:23:55 2011 +0200
@@ -30,7 +30,8 @@
 - (NSImage *)imageByScalingToSize:(NSSize)size fraction:(CGFloat)delta;
 - (NSImage *)imageByScalingForMenuItem;
 - (NSImage *)imageByScalingToSize:(NSSize)size fraction:(CGFloat)delta flipImage:(BOOL)flipImage proportionally:(BOOL)proportionally allowAnimation:(BOOL)allowAnimation;
-//+ (NSImage *)imageFromGWorld:(GWorldPtr)gWorldPtr;
+- (NSImage *)imageByFittingInSize:(NSSize)size;
+- (NSImage *)imageByFittingInSize:(NSSize)size fraction:(CGFloat)delta flipImage:(BOOL)flipImage proportionally:(BOOL)proportionally allowAnimation:(BOOL)allowAnimation;
 - (NSRect)drawRoundedInRect:(NSRect)rect radius:(CGFloat)radius;
 - (NSRect)drawRoundedInRect:(NSRect)rect fraction:(CGFloat)inFraction radius:(CGFloat)radius;
 - (NSRect)drawRoundedInRect:(NSRect)rect atSize:(NSSize)size position:(IMAGE_POSITION)position fraction:(CGFloat)inFraction radius:(CGFloat)radius;
diff -r 5721d368ee1b -r fd7808a9f165 Frameworks/AIUtilities Framework/Source/AIImageDrawingAdditions.m
--- a/Frameworks/AIUtilities Framework/Source/AIImageDrawingAdditions.m	Mon Mar 21 07:20:32 2011 -0700
+++ b/Frameworks/AIUtilities Framework/Source/AIImageDrawingAdditions.m	Sat Mar 26 23:23:55 2011 +0200
@@ -15,11 +15,14 @@
  */
 
 #import "AIImageDrawingAdditions.h"
+#import "AIImageAdditions.h"
 #import "AIBezierPathAdditions.h"
 
+
 @implementation NSImage (AIImageDrawingAdditions)
 
-//Draw this image in a rect, tiling if the rect is larger than the image
+
+// Draw this image in a rect, tiling if the rect is larger than the image
 - (void)tileInRect:(NSRect)rect
 {
     NSSize	size = [self size];
@@ -27,24 +30,26 @@
     CGFloat	top = rect.origin.y + rect.size.height;
     CGFloat	right = rect.origin.x + rect.size.width;
     
-    //Tile vertically
+    // Tile vertically
     while (destRect.origin.y < top) {
-		//Tile horizontally
+		// Tile horizontally
 		while (destRect.origin.x < right) {
 			NSRect  sourceRect = NSMakeRect(0, 0, size.width, size.height);
 			
-			//Crop as necessary
+			// Crop as necessary
 			if ((destRect.origin.x + destRect.size.width) > right) {
 				sourceRect.size.width -= (destRect.origin.x + destRect.size.width) - right;
 			}
+			
 			if ((destRect.origin.y + destRect.size.height) > top) {
 				sourceRect.size.height -= (destRect.origin.y + destRect.size.height) - top;
 			}
 			
-			//Draw and shift
+			// Draw and shift
 			[self compositeToPoint:destRect.origin fromRect:sourceRect operation:NSCompositeSourceOver];
 			destRect.origin.x += destRect.size.width;
 		}
+		
 		destRect.origin.y += destRect.size.height;
     }
 }
@@ -75,9 +80,9 @@
 
 - (NSImage *)imageByScalingToSize:(NSSize)size fraction:(CGFloat)delta flipImage:(BOOL)flipImage proportionally:(BOOL)proportionally allowAnimation:(BOOL)allowAnimation
 {
-	NSSize  originalSize = [self size];
+	NSSize originalSize = [self size];
 	
-	//Proceed only if size or delta are changing
+	// Proceed only if size or delta are changing
 	if ((NSEqualSizes(originalSize, size)) && (delta == 1.0) && !flipImage) {
 		return [[self copy] autorelease];
 		
@@ -85,37 +90,75 @@
 		NSImage *newImage;
 		NSRect	newRect;
 		
-		//Scale proportionally (rather than stretching to fit) if requested and needed
+		// Scale proportionally (rather than stretching to fit) if requested and needed
 		if (proportionally && (originalSize.width != originalSize.height)) {
 			if (originalSize.width > originalSize.height) {
-				//Give width priority: Make the height change by the same proportion as the width will change
+				// Give width priority: Make the height change by the same proportion as the width will change
 				size.height = originalSize.height * (size.width / originalSize.width);
 			} else {
-				//Give height priority: Make the width change by the same proportion as the height will change
+				// Give height priority: Make the width change by the same proportion as the height will change
 				size.width = originalSize.width * (size.height / originalSize.height);
 			}
 		}
 		
-		newRect = NSMakeRect(0,0,size.width,size.height);
+		newRect = NSMakeRect(0.0f, 0.0f, size.width, size.height);
 		newImage = [[NSImage alloc] initWithSize:size];
 		
-		if (flipImage) [newImage setFlipped:YES];		
+		if (flipImage) {
+			[newImage setFlipped:YES];		
+		}
 		
-		NSImageRep	*bestRep;
+		NSImageRep *bestRep;
+		
 		if (allowAnimation &&
 			(bestRep = [self bestRepresentationForRect:NSMakeRect(0, 0, self.size.width, self.size.height) context:nil hints:nil]) &&
 			[bestRep isKindOfClass:[NSBitmapImageRep class]] && 
 			(delta == 1.0) &&
 			([[(NSBitmapImageRep *)bestRep valueForProperty:NSImageFrameCount] intValue] > 1) ) {
-			//We've got an animating file, and the current alpha is fine.  Just copy the representation.
-			[newImage addRepresentation:[[bestRep copy] autorelease]];
 			
+			// We've got an animating file, and the current alpha is fine.  Just copy the representation.
+			NSMutableData *GIFRepresentationData = nil;
+
+			unsigned frameCount = [[(NSBitmapImageRep *)bestRep valueForProperty:NSImageFrameCount] intValue];
+			
+			if (!frameCount) {
+				frameCount = 1;
+			}
+			
+			NSMutableArray *images = [NSMutableArray array];
+			
+			for (unsigned i = 0; i < frameCount; i++) {
+				// Set current frame
+				[(NSBitmapImageRep *)bestRep setProperty:NSImageCurrentFrame withValue:[NSNumber numberWithUnsignedInt:i]];
+				
+				[newImage lockFocus];
+				
+				[self drawInRect:newRect
+						fromRect:NSMakeRect(0.0f, 0.0f, originalSize.width, originalSize.height)
+					   operation:NSCompositeCopy
+						fraction:delta];
+				
+				[newImage unlockFocus];
+				
+				// Add frame representation
+				[images addObject:[NSBitmapImageRep imageRepWithData:[newImage TIFFRepresentation]]];
+			}
+			
+			GIFRepresentationData = [NSMutableData dataWithData:[NSBitmapImageRep representationOfImageRepsInArray:images
+																										 usingType:NSGIFFileType
+																										properties:[self GIFPropertiesForRepresentation:(NSBitmapImageRep *)bestRep]]];
+			
+			// Write GIF Extension Blocks
+			[self writeGIFExtensionBlocksInData:GIFRepresentationData forRepresenation:(NSBitmapImageRep *)bestRep];
+			
+			newImage = [[NSImage alloc] initWithData:GIFRepresentationData];
 		} else {
 			[newImage lockFocus];
-			//Highest quality interpolation
+			// Highest quality interpolation
 			[[NSGraphicsContext currentContext] setImageInterpolation:NSImageInterpolationHigh];
+			
 			[self drawInRect:newRect
-					fromRect:NSMakeRect(0,0,originalSize.width,originalSize.height)
+					fromRect:NSMakeRect(0.0f, 0.0f, originalSize.width, originalSize.height)
 				   operation:NSCompositeCopy
 					fraction:delta];
 			
@@ -126,119 +169,176 @@
 	}
 }
 
-/*+ (NSImage *)imageFromGWorld:(GWorldPtr)gworld
- {
- NSParameterAssert(gworld != NULL);
- 
- PixMapHandle pixMapHandle = GetGWorldPixMap( gworld );
- if (LockPixels(pixMapHandle)) {
- Rect 	portRect;
- 
- GetPortBounds( gworld, &portRect );
- 
- int 	pixels_wide = (portRect.right - portRect.left);
- int 	pixels_high = (portRect.bottom - portRect.top);
- int 	bps = 8;
- int 	spp = 4;
- BOOL 	has_alpha = YES;
- 
- NSBitmapImageRep *bitmap_rep = [[[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL
- pixelsWide:pixels_wide
- pixelsHigh:pixels_high
- bitsPerSample:bps
- samplesPerPixel:spp
- hasAlpha:has_alpha
- isPlanar:NO
- colorSpaceName:NSDeviceRGBColorSpace
- bytesPerRow:0
- bitsPerPixel:0] autorelease];
- CGColorSpaceRef 	dst_colorspaceref = CGColorSpaceCreateDeviceRGB();
- CGImageAlphaInfo 	dst_alphainfo = has_alpha ? kCGImageAlphaPremultipliedLast : kCGImageAlphaNone;
- CGContextRef 		dst_contextref = CGBitmapContextCreate([bitmap_rep bitmapData],
- pixels_wide,
- pixels_high,
- bps,
- [bitmap_rep bytesPerRow],
- dst_colorspaceref,
- dst_alphainfo);
- void *pixBaseAddr = GetPixBaseAddr(pixMapHandle);
- long pixmapRowBytes = GetPixRowBytes(pixMapHandle);
- 
- CGDataProviderRef dataproviderref = CGDataProviderCreateWithData(NULL, pixBaseAddr, pixmapRowBytes * pixels_high, NULL);
- 
- int src_bps = 8;
- int src_spp = 4;
- BOOL src_has_alpha = YES;
- 
- CGColorSpaceRef src_colorspaceref = CGColorSpaceCreateDeviceRGB();
- 
- CGImageAlphaInfo src_alphainfo = src_has_alpha ? kCGImageAlphaPremultipliedFirst : kCGImageAlphaNone;
- 
- CGImageRef src_imageref = CGImageCreate(pixels_wide,
- pixels_high,
- src_bps,
- src_bps * src_spp,
- pixmapRowBytes,
- src_colorspaceref,
- src_alphainfo,
- dataproviderref,
- NULL,
- NO, // shouldInterpolate
- kCGRenderingIntentDefault);
- 
- CGRect rect = CGRectMake(0, 0, pixels_wide, pixels_high);
- 
- CGContextDrawImage(dst_contextref, rect, src_imageref);
- 
- CGImageRelease(src_imageref);
- CGColorSpaceRelease(src_colorspaceref);
- CGDataProviderRelease(dataproviderref);
- CGContextRelease(dst_contextref);
- CGColorSpaceRelease(dst_colorspaceref);
- 
- UnlockPixels(pixMapHandle);
- 
- NSImage *image = [[[NSImage alloc] initWithSize:NSMakeSize(pixels_wide, pixels_high)] autorelease];
- [image addRepresentation:bitmap_rep];
- return image;
- }
- return nil;
- }*/
+- (NSImage *)imageByFittingInSize:(NSSize)size
+{
+	return ([self imageByFittingInSize:size fraction:1.0f flipImage:NO proportionally:YES allowAnimation:YES]);
+}
 
-//Fun drawing toys
-//Draw an image, altering and returning the available destination rect
+- (NSImage *)imageByFittingInSize:(NSSize)size fraction:(CGFloat)delta flipImage:(BOOL)flipImage proportionally:(BOOL)proportionally allowAnimation:(BOOL)allowAnimation
+{
+	NSSize originalSize = [self size];
+	NSSize scaleSize = size;
+	NSSize fitSize = size;
+	
+	// Proceed only if size or delta are changing
+	if ((NSEqualSizes(originalSize, size)) && (delta == 1.0) && !flipImage) {
+		return [[self copy] autorelease];
+		
+	} else {
+		// Scale proportionally (rather than stretching to fit) if requested and needed
+		if (proportionally && (originalSize.width != originalSize.height)) {
+			if (originalSize.width > originalSize.height) {
+				// Give width priority: Make the height change by the same proportion as the width will change
+				scaleSize.height = originalSize.height * (size.width / originalSize.width);
+			} else {
+				// Give height priority: Make the width change by the same proportion as the height will change
+				scaleSize.width = originalSize.width * (size.height / originalSize.height);
+			}
+		}
+		
+		// Fit
+		if (proportionally && (originalSize.width != originalSize.height)) {
+			if (originalSize.width > originalSize.height) {
+				// Give width priority: Make the height change by the same proportion as the width will change
+				fitSize.height = originalSize.height * (size.width / originalSize.width);
+			} else {
+				// Give height priority: Make the width change by the same proportion as the height will change
+				fitSize.width = originalSize.width * (size.height / originalSize.height);
+			}
+		}
+		
+		NSRect scaleRect = NSMakeRect(0.0f, 0.0f, scaleSize.width, scaleSize.height);
+		NSPoint fitFromPoint = NSMakePoint((size.width - scaleSize.width) / 2.0f, (size.height - scaleSize.height) / 2.0f);
+		
+		NSImage *newImage = [[NSImage alloc] initWithSize:size];
+		NSImage *scaledImage = [[NSImage alloc] initWithSize:scaleSize];
+		
+		if (flipImage) {
+			[newImage setFlipped:YES];		
+		}
+		
+		NSImageRep *bestRep;
+		
+		if (allowAnimation &&
+			(bestRep = [self bestRepresentationForRect:NSMakeRect(0, 0, self.size.width, self.size.height) context:nil hints:nil]) &&
+			[bestRep isKindOfClass:[NSBitmapImageRep class]] && 
+			(delta == 1.0) &&
+			([[(NSBitmapImageRep *)bestRep valueForProperty:NSImageFrameCount] intValue] > 1) ) {
+			
+			// We've got an animating file, and the current alpha is fine.  Just copy the representation.
+			NSMutableData *GIFRepresentationData = nil;
+
+			unsigned frameCount = [[(NSBitmapImageRep *)bestRep valueForProperty:NSImageFrameCount] intValue];
+			
+			if (!frameCount) {
+				frameCount = 1;
+			}
+			
+			NSMutableArray *images = [NSMutableArray array];
+			
+			for (unsigned i = 0; i < frameCount; i++) {
+				// Set current frame
+				[(NSBitmapImageRep *)bestRep setProperty:NSImageCurrentFrame withValue:[NSNumber numberWithUnsignedInt:i]];
+				
+				[scaledImage lockFocus];
+				
+				// Scale
+				[self drawInRect:scaleRect
+						fromRect:NSMakeRect(0.0f, 0.0f, originalSize.width, originalSize.height)
+					   operation:NSCompositeCopy
+						fraction:delta];
+				
+				[scaledImage unlockFocus];
+				[newImage lockFocus];
+				
+				// Fit
+				[scaledImage drawAtPoint:fitFromPoint
+						 fromRect:NSMakeRect(0.0f, 0.0f, newImage.size.width, newImage.size.height)
+						operation:NSCompositeCopy
+						 fraction:delta];
+				
+				[newImage unlockFocus];
+				
+				// Add frame representation
+				[images addObject:[NSBitmapImageRep imageRepWithData:[newImage TIFFRepresentation]]];
+			}
+			
+			GIFRepresentationData = [NSMutableData dataWithData:[NSBitmapImageRep representationOfImageRepsInArray:images
+																										 usingType:NSGIFFileType
+																										properties:[self GIFPropertiesForRepresentation:(NSBitmapImageRep *)bestRep]]];
+			
+			// Write GIF Extension Blocks
+			[self writeGIFExtensionBlocksInData:GIFRepresentationData forRepresenation:(NSBitmapImageRep *)bestRep];
+			
+			newImage = [[NSImage alloc] initWithData:GIFRepresentationData];
+		} else {
+			[scaledImage lockFocus];
+			// Highest quality interpolation
+			[[NSGraphicsContext currentContext] setImageInterpolation:NSImageInterpolationHigh];
+			
+			// Scale
+			[self drawInRect:scaleRect
+					fromRect:NSMakeRect(0.0f, 0.0f, originalSize.width, originalSize.height)
+				   operation:NSCompositeCopy
+					fraction:delta];
+			
+			[scaledImage unlockFocus];
+			[newImage lockFocus];
+			
+			// Fit
+			[scaledImage drawAtPoint:fitFromPoint
+							fromRect:NSMakeRect(0.0f, 0.0f, newImage.size.width, newImage.size.height)
+						   operation:NSCompositeCopy
+							fraction:delta];




More information about the commits mailing list