Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

first commit

  • Loading branch information...
commit b452aa0568f82f041ea777888ebf30980ee97682 0 parents
Matt Gemmell mattgemmell authored
31 Classes/MGImageUtilitiesAppDelegate.h
... ... @@ -0,0 +1,31 @@
  1 +//
  2 +// MGImageUtilitiesAppDelegate.h
  3 +// MGImageUtilities
  4 +//
  5 +// Created by Matt Gemmell on 04/07/2010.
  6 +// Copyright Instinctive Code 2010.
  7 +//
  8 +
  9 +#import <UIKit/UIKit.h>
  10 +
  11 +@interface MGImageUtilitiesAppDelegate : NSObject <UIApplicationDelegate> {
  12 + UIWindow *window;
  13 + UIImageView *originalView;
  14 + UIImageView *resultView;
  15 + UISegmentedControl *methodControl;
  16 + UISwitch *tintSwitch;
  17 +}
  18 +
  19 +@property (nonatomic, retain) IBOutlet UIWindow *window;
  20 +@property (nonatomic, retain) IBOutlet UIImageView *originalView;
  21 +@property (nonatomic, retain) IBOutlet UIImageView *resultView;
  22 +@property (nonatomic, retain) IBOutlet UISegmentedControl *methodControl;
  23 +@property (nonatomic, retain) IBOutlet UISwitch *tintSwitch;
  24 +
  25 +- (IBAction)methodChanged:(id)sender;
  26 +- (IBAction)tintChanged:(id)sender;
  27 +
  28 +- (void)updateResult;
  29 +
  30 +@end
  31 +
88 Classes/MGImageUtilitiesAppDelegate.m
... ... @@ -0,0 +1,88 @@
  1 +//
  2 +// MGImageUtilitiesAppDelegate.m
  3 +// MGImageUtilities
  4 +//
  5 +// Created by Matt Gemmell on 04/07/2010.
  6 +// Copyright Instinctive Code 2010.
  7 +//
  8 +
  9 +#import "MGImageUtilitiesAppDelegate.h"
  10 +#import "UIImage+ProportionalFill.h"
  11 +#import "UIImage+Tint.h"
  12 +
  13 +@implementation MGImageUtilitiesAppDelegate
  14 +
  15 +
  16 +@synthesize window;
  17 +@synthesize originalView;
  18 +@synthesize resultView;
  19 +@synthesize methodControl;
  20 +@synthesize tintSwitch;
  21 +
  22 +
  23 +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
  24 +{
  25 + // Load a sample image for the demo.
  26 + originalView.image = [UIImage imageNamed:@"original.png"];
  27 + [self updateResult];
  28 +
  29 + [window makeKeyAndVisible];
  30 +
  31 + return YES;
  32 +}
  33 +
  34 +
  35 +- (void)dealloc
  36 +{
  37 + [window release];
  38 +
  39 + [super dealloc];
  40 +}
  41 +
  42 +
  43 +- (IBAction)methodChanged:(id)sender
  44 +{
  45 + [self updateResult];
  46 +}
  47 +
  48 +
  49 +- (IBAction)tintChanged:(id)sender
  50 +{
  51 + [self updateResult];
  52 +}
  53 +
  54 +
  55 +- (void)updateResult
  56 +{
  57 + UIImage *oldImage = originalView.image;
  58 + UIImage *newImage;
  59 + CGSize newSize = resultView.frame.size;
  60 +
  61 + // Resize the image using the user's chosen method.
  62 + switch (methodControl.selectedSegmentIndex) {
  63 + case 0:
  64 + newImage = [oldImage imageScaledToFitSize:newSize]; // uses MGImageResizeScale
  65 + break;
  66 + case 1:
  67 + newImage = [oldImage imageCroppedToFitSize:newSize]; // uses MGImageResizeCrop
  68 + break;
  69 + case 2:
  70 + newImage = [oldImage imageToFitSize:newSize method:MGImageResizeCropStart];
  71 + break;
  72 + case 3:
  73 + newImage = [oldImage imageToFitSize:newSize method:MGImageResizeCropEnd];
  74 + break;
  75 + default:
  76 + break;
  77 + }
  78 +
  79 + // If appropriate, tint the resulting image.
  80 + if (tintSwitch.on) {
  81 + newImage = [newImage imageTintedWithColor:[UIColor redColor]];
  82 + }
  83 +
  84 + resultView.image = newImage;
  85 +}
  86 +
  87 +
  88 +@end
23 Classes/UIImage+ProportionalFill.h
... ... @@ -0,0 +1,23 @@
  1 +//
  2 +// UIImage+ProportionalFill.h
  3 +//
  4 +// Created by Matt Gemmell on 20/08/2008.
  5 +// Copyright 2008 Instinctive Code.
  6 +//
  7 +
  8 +#import <UIKit/UIKit.h>
  9 +
  10 +@interface UIImage (MGProportionalFill)
  11 +
  12 +typedef enum {
  13 + MGImageResizeCrop, // analogous to UIViewContentModeScaleAspectFill, i.e. "best fit" with no space around.
  14 + MGImageResizeCropStart,
  15 + MGImageResizeCropEnd,
  16 + MGImageResizeScale // analogous to UIViewContentModeScaleAspectFit, i.e. scale down to fit, leaving space around if necessary.
  17 +} MGImageResizingMethod;
  18 +
  19 +- (UIImage *)imageToFitSize:(CGSize)size method:(MGImageResizingMethod)resizeMethod;
  20 +- (UIImage *)imageCroppedToFitSize:(CGSize)size; // uses MGImageResizeCrop
  21 +- (UIImage *)imageScaledToFitSize:(CGSize)size; // uses MGImageResizeScale
  22 +
  23 +@end
109 Classes/UIImage+ProportionalFill.m
... ... @@ -0,0 +1,109 @@
  1 +//
  2 +// UIImage+ProportionalFill.m
  3 +//
  4 +// Created by Matt Gemmell on 20/08/2008.
  5 +// Copyright 2008 Instinctive Code.
  6 +//
  7 +
  8 +#import "UIImage+ProportionalFill.h"
  9 +
  10 +
  11 +@implementation UIImage (MGProportionalFill)
  12 +
  13 +
  14 +- (UIImage *)imageToFitSize:(CGSize)fitSize method:(MGImageResizingMethod)resizeMethod
  15 +{
  16 + float sourceWidth = [self size].width * self.scale;
  17 + float sourceHeight = [self size].height * self.scale;
  18 + float targetWidth = fitSize.width;
  19 + float targetHeight = fitSize.height;
  20 + BOOL cropping = !(resizeMethod == MGImageResizeScale);
  21 +
  22 + // Calculate aspect ratios
  23 + float sourceRatio = sourceWidth / sourceHeight;
  24 + float targetRatio = targetWidth / targetHeight;
  25 +
  26 + // Determine what side of the source image to use for proportional scaling
  27 + BOOL scaleWidth = (sourceRatio <= targetRatio);
  28 + // Deal with the case of just scaling proportionally to fit, without cropping
  29 + scaleWidth = (cropping) ? scaleWidth : !scaleWidth;
  30 +
  31 + // Proportionally scale source image
  32 + float scalingFactor, scaledWidth, scaledHeight;
  33 + if (scaleWidth) {
  34 + scalingFactor = 1.0 / sourceRatio;
  35 + scaledWidth = targetWidth;
  36 + scaledHeight = round(targetWidth * scalingFactor);
  37 + } else {
  38 + scalingFactor = sourceRatio;
  39 + scaledWidth = round(targetHeight * scalingFactor);
  40 + scaledHeight = targetHeight;
  41 + }
  42 + float scaleFactor = scaledHeight / sourceHeight;
  43 +
  44 + // Calculate compositing rectangles
  45 + CGRect sourceRect, destRect;
  46 + if (cropping) {
  47 + destRect = CGRectMake(0, 0, targetWidth, targetHeight);
  48 + float destX, destY;
  49 + if (resizeMethod == MGImageResizeCrop) {
  50 + // Crop center
  51 + destX = round((scaledWidth - targetWidth) / 2.0);
  52 + destY = round((scaledHeight - targetHeight) / 2.0);
  53 + } else if (resizeMethod == MGImageResizeCropStart) {
  54 + // Crop top or left (prefer top)
  55 + if (scaleWidth) {
  56 + // Crop top
  57 + destX = 0.0;
  58 + destY = 0.0;
  59 + } else {
  60 + // Crop left
  61 + destX = 0.0;
  62 + destY = round((scaledHeight - targetHeight) / 2.0);
  63 + }
  64 + } else if (resizeMethod == MGImageResizeCropEnd) {
  65 + // Crop bottom or right
  66 + if (scaleWidth) {
  67 + // Crop bottom
  68 + destX = round((scaledWidth - targetWidth) / 2.0);
  69 + destY = round(scaledHeight - targetHeight);
  70 + } else {
  71 + // Crop right
  72 + destX = round(scaledWidth - targetWidth);
  73 + destY = round((scaledHeight - targetHeight) / 2.0);
  74 + }
  75 + }
  76 + sourceRect = CGRectMake(destX / scaleFactor, destY / scaleFactor,
  77 + targetWidth / scaleFactor, targetHeight / scaleFactor);
  78 + } else {
  79 + sourceRect = CGRectMake(0, 0, sourceWidth, sourceHeight);
  80 + destRect = CGRectMake(0, 0, scaledWidth, scaledHeight);
  81 + }
  82 +
  83 + // Create appropriately modified image.
  84 + UIImage *image;
  85 + UIGraphicsBeginImageContextWithOptions(destRect.size, NO, 0.0); // 0.0 for scale means "correct scale for device's main screen".
  86 + CGImageRef sourceImg = CGImageCreateWithImageInRect([self CGImage], sourceRect); // cropping happens here.
  87 + image = [UIImage imageWithCGImage:sourceImg scale:0.0 orientation:self.imageOrientation]; // create cropped UIImage.
  88 + [image drawInRect:destRect]; // the actual scaling happens here, and orientation is taken care of automatically.
  89 + CGImageRelease(sourceImg);
  90 + image = UIGraphicsGetImageFromCurrentImageContext();
  91 + UIGraphicsEndImageContext();
  92 +
  93 + return image;
  94 +}
  95 +
  96 +
  97 +- (UIImage *)imageCroppedToFitSize:(CGSize)fitSize
  98 +{
  99 + return [self imageToFitSize:fitSize method:MGImageResizeCrop];
  100 +}
  101 +
  102 +
  103 +- (UIImage *)imageScaledToFitSize:(CGSize)fitSize
  104 +{
  105 + return [self imageToFitSize:fitSize method:MGImageResizeScale];
  106 +}
  107 +
  108 +
  109 +@end
15 Classes/UIImage+Tint.h
... ... @@ -0,0 +1,15 @@
  1 +//
  2 +// UIImage+Tint.h
  3 +//
  4 +// Created by Matt Gemmell on 04/07/2010.
  5 +// Copyright 2010 Instinctive Code.
  6 +//
  7 +
  8 +#import <UIKit/UIKit.h>
  9 +
  10 +@interface UIImage (MGTint)
  11 +
  12 +- (UIImage *)imageTintedWithColor:(UIColor *)color;
  13 +- (UIImage *)imageTintedWithColor:(UIColor *)color fraction:(CGFloat)fraction;
  14 +
  15 +@end
54 Classes/UIImage+Tint.m
... ... @@ -0,0 +1,54 @@
  1 +//
  2 +// UIImage+Tint.m
  3 +//
  4 +// Created by Matt Gemmell on 04/07/2010.
  5 +// Copyright 2010 Instinctive Code.
  6 +//
  7 +
  8 +#import "UIImage+Tint.h"
  9 +
  10 +
  11 +@implementation UIImage (MGTint)
  12 +
  13 +
  14 +- (UIImage *)imageTintedWithColor:(UIColor *)color
  15 +{
  16 + // This method is designed for use with template images, i.e. solid-coloured mask-like images.
  17 + return [self imageTintedWithColor:color fraction:0.0]; // default to a fully tinted mask of the image.
  18 +}
  19 +
  20 +
  21 +- (UIImage *)imageTintedWithColor:(UIColor *)color fraction:(CGFloat)fraction
  22 +{
  23 + if (color) {
  24 + // Construct new image the same size as this one.
  25 + UIImage *image;
  26 + UIGraphicsBeginImageContextWithOptions([self size], NO, 0.0); // 0.0 for scale means "scale for device's main screen".
  27 + CGRect rect = CGRectZero;
  28 + rect.size = [self size];
  29 +
  30 + // Composite tint color at its own opacity.
  31 + [color set];
  32 + UIRectFill(rect);
  33 +
  34 + // Mask tint color-swatch to this image's opaque mask.
  35 + // We want behaviour like NSCompositeDestinationIn on Mac OS X.
  36 + [self drawInRect:rect blendMode:kCGBlendModeDestinationIn alpha:1.0];
  37 +
  38 + // Finally, composite this image over the tinted mask at desired opacity.
  39 + if (fraction > 0.0) {
  40 + // We want behaviour like NSCompositeSourceOver on Mac OS X.
  41 + [self drawInRect:rect blendMode:kCGBlendModeSourceAtop alpha:fraction];
  42 + }
  43 + image = UIGraphicsGetImageFromCurrentImageContext();
  44 + UIGraphicsEndImageContext();
  45 +
  46 + return image;
  47 + }
  48 +
  49 + return self;
  50 +}
  51 +
  52 +
  53 +
  54 +@end
30 MGImageUtilities-Info.plist
... ... @@ -0,0 +1,30 @@
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
  3 +<plist version="1.0">
  4 +<dict>
  5 + <key>CFBundleDevelopmentRegion</key>
  6 + <string>English</string>
  7 + <key>CFBundleDisplayName</key>
  8 + <string>${PRODUCT_NAME}</string>
  9 + <key>CFBundleExecutable</key>
  10 + <string>${EXECUTABLE_NAME}</string>
  11 + <key>CFBundleIconFile</key>
  12 + <string></string>
  13 + <key>CFBundleIdentifier</key>
  14 + <string>com.instinctivecode.test.${PRODUCT_NAME:rfc1034identifier}</string>
  15 + <key>CFBundleInfoDictionaryVersion</key>
  16 + <string>6.0</string>
  17 + <key>CFBundleName</key>
  18 + <string>${PRODUCT_NAME}</string>
  19 + <key>CFBundlePackageType</key>
  20 + <string>APPL</string>
  21 + <key>CFBundleSignature</key>
  22 + <string>????</string>
  23 + <key>CFBundleVersion</key>
  24 + <string>1.0</string>
  25 + <key>LSRequiresIPhoneOS</key>
  26 + <true/>
  27 + <key>NSMainNibFile</key>
  28 + <string>MainWindow</string>
  29 +</dict>
  30 +</plist>
257 MGImageUtilities.xcodeproj/matt.pbxuser
... ... @@ -0,0 +1,257 @@
  1 +// !$*UTF8*$!
  2 +{
  3 + 1D3623240D0F684500981E51 /* MGImageUtilitiesAppDelegate.h */ = {
  4 + uiCtxt = {
  5 + sepNavIntBoundsRect = "{{0, 0}, {1014, 978}}";
  6 + sepNavSelRange = "{140, 0}";
  7 + sepNavVisRange = "{0, 811}";
  8 + };
  9 + };
  10 + 1D3623250D0F684500981E51 /* MGImageUtilitiesAppDelegate.m */ = {
  11 + uiCtxt = {
  12 + sepNavIntBoundsRect = "{{0, 0}, {958, 1188}}";
  13 + sepNavSelRange = "{684, 0}";
  14 + sepNavVisRange = "{61, 812}";
  15 + };
  16 + };
  17 + 1D6058900D05DD3D006BFB54 /* MGImageUtilities */ = {
  18 + activeExec = 0;
  19 + executables = (
  20 + C901792211E13124002B9BA3 /* MGImageUtilities */,
  21 + );
  22 + };
  23 + 29B97313FDCFA39411CA2CEA /* Project object */ = {
  24 + activeBuildConfigurationName = Debug;
  25 + activeExecutable = C901792211E13124002B9BA3 /* MGImageUtilities */;
  26 + activeSDKPreference = iphonesimulator4.0;
  27 + activeTarget = 1D6058900D05DD3D006BFB54 /* MGImageUtilities */;
  28 + addToTargets = (
  29 + 1D6058900D05DD3D006BFB54 /* MGImageUtilities */,
  30 + );
  31 + codeSenseManager = C901793011E13130002B9BA3 /* Code sense */;
  32 + executables = (
  33 + C901792211E13124002B9BA3 /* MGImageUtilities */,
  34 + );
  35 + perUserDictionary = {
  36 + PBXConfiguration.PBXFileTableDataSource3.PBXFileTableDataSource = {
  37 + PBXFileTableDataSourceColumnSortingDirectionKey = "-1";
  38 + PBXFileTableDataSourceColumnSortingKey = PBXFileDataSource_Filename_ColumnID;
  39 + PBXFileTableDataSourceColumnWidthsKey = (
  40 + 20,
  41 + 10,
  42 + 20,
  43 + 48,
  44 + 43,
  45 + 43,
  46 + 20,
  47 + );
  48 + PBXFileTableDataSourceColumnsKey = (
  49 + PBXFileDataSource_FiletypeID,
  50 + PBXFileDataSource_Filename_ColumnID,
  51 + PBXFileDataSource_Built_ColumnID,
  52 + PBXFileDataSource_ObjectSize_ColumnID,
  53 + PBXFileDataSource_Errors_ColumnID,
  54 + PBXFileDataSource_Warnings_ColumnID,
  55 + PBXFileDataSource_Target_ColumnID,
  56 + );
  57 + };
  58 + PBXPerProjectTemplateStateSaveDate = 300009815;
  59 + PBXWorkspaceStateSaveDate = 300009815;
  60 + };
  61 + perUserProjectItems = {
  62 + C901795811E1357E002B9BA3 /* PBXTextBookmark */ = C901795811E1357E002B9BA3 /* PBXTextBookmark */;
  63 + C901795A11E1357E002B9BA3 /* PBXTextBookmark */ = C901795A11E1357E002B9BA3 /* PBXTextBookmark */;
  64 + C901798611E13A73002B9BA3 /* PBXBookmark */ = C901798611E13A73002B9BA3 /* PBXBookmark */;
  65 + C901798911E13A73002B9BA3 /* PBXTextBookmark */ = C901798911E13A73002B9BA3 /* PBXTextBookmark */;
  66 + C9017A1311E14592002B9BA3 /* PBXTextBookmark */ = C9017A1311E14592002B9BA3 /* PBXTextBookmark */;
  67 + C9017A7F11E14AD6002B9BA3 /* PBXTextBookmark */ = C9017A7F11E14AD6002B9BA3 /* PBXTextBookmark */;
  68 + C9017A8711E14BC5002B9BA3 /* PBXTextBookmark */ = C9017A8711E14BC5002B9BA3 /* PBXTextBookmark */;
  69 + C9017A8811E14BC5002B9BA3 /* PBXTextBookmark */ = C9017A8811E14BC5002B9BA3 /* PBXTextBookmark */;
  70 + C9D4927E11E1D09400B63B06 /* PBXTextBookmark */ = C9D4927E11E1D09400B63B06 /* PBXTextBookmark */;
  71 + C9D4928011E1D0B600B63B06 /* PBXTextBookmark */ = C9D4928011E1D0B600B63B06 /* PBXTextBookmark */;
  72 + };
  73 + sourceControlManager = C901792F11E13130002B9BA3 /* Source Control */;
  74 + userBuildSettings = {
  75 + };
  76 + };
  77 + C901792211E13124002B9BA3 /* MGImageUtilities */ = {
  78 + isa = PBXExecutable;
  79 + activeArgIndices = (
  80 + );
  81 + argumentStrings = (
  82 + );
  83 + autoAttachOnCrash = 1;
  84 + breakpointsEnabled = 0;
  85 + configStateDict = {
  86 + };
  87 + customDataFormattersEnabled = 1;
  88 + dataTipCustomDataFormattersEnabled = 1;
  89 + dataTipShowTypeColumn = 1;
  90 + dataTipSortType = 0;
  91 + debuggerPlugin = GDBDebugging;
  92 + disassemblyDisplayState = 0;
  93 + dylibVariantSuffix = "";
  94 + enableDebugStr = 1;
  95 + environmentEntries = (
  96 + );
  97 + executableSystemSymbolLevel = 0;
  98 + executableUserSymbolLevel = 0;
  99 + libgmallocEnabled = 0;
  100 + name = MGImageUtilities;
  101 + savedGlobals = {
  102 + };
  103 + showTypeColumn = 0;
  104 + sourceDirectories = (
  105 + );
  106 + };
  107 + C901792F11E13130002B9BA3 /* Source Control */ = {
  108 + isa = PBXSourceControlManager;
  109 + fallbackIsa = XCSourceControlManager;
  110 + isSCMEnabled = 0;
  111 + scmConfiguration = {
  112 + repositoryNamesForRoots = {
  113 + "" = "";
  114 + };
  115 + };
  116 + };
  117 + C901793011E13130002B9BA3 /* Code sense */ = {
  118 + isa = PBXCodeSenseManager;
  119 + indexTemplatePath = "";
  120 + };
  121 + C901793F11E13174002B9BA3 /* UIImage+ProportionalFill.h */ = {
  122 + uiCtxt = {
  123 + sepNavIntBoundsRect = "{{0, 0}, {1013, 763}}";
  124 + sepNavSelRange = "{116, 0}";
  125 + sepNavVisRange = "{0, 765}";
  126 + };
  127 + };
  128 + C901794011E13174002B9BA3 /* UIImage+ProportionalFill.m */ = {
  129 + uiCtxt = {
  130 + sepNavIntBoundsRect = "{{0, 0}, {958, 1320}}";
  131 + sepNavSelRange = "{3477, 0}";
  132 + sepNavVisRange = "{2038, 1740}";
  133 + };
  134 + };
  135 + C901794111E13174002B9BA3 /* UIImage+Tint.h */ = {
  136 + uiCtxt = {
  137 + sepNavIntBoundsRect = "{{0, 0}, {1013, 763}}";
  138 + sepNavSelRange = "{104, 0}";
  139 + sepNavVisRange = "{0, 300}";
  140 + };
  141 + };
  142 + C901794211E13174002B9BA3 /* UIImage+Tint.m */ = {
  143 + uiCtxt = {
  144 + sepNavIntBoundsRect = "{{0, 0}, {1014, 978}}";
  145 + sepNavSelRange = "{426, 0}";
  146 + sepNavVisRange = "{0, 1430}";
  147 + };
  148 + };
  149 + C901795511E1354F002B9BA3 /* Source Code License.rtf */ = {
  150 + uiCtxt = {
  151 + sepNavIntBoundsRect = "{{0, 0}, {1028, 1048}}";
  152 + sepNavSelRange = "{1588, 0}";
  153 + sepNavVisRect = "{{0, 0}, {1028, 993}}";
  154 + };
  155 + };
  156 + C901795811E1357E002B9BA3 /* PBXTextBookmark */ = {
  157 + isa = PBXTextBookmark;
  158 + fRef = C901794111E13174002B9BA3 /* UIImage+Tint.h */;
  159 + name = "UIImage+Tint.h: 5";
  160 + rLen = 0;
  161 + rLoc = 104;
  162 + rType = 0;
  163 + vrLen = 300;
  164 + vrLoc = 0;
  165 + };
  166 + C901795A11E1357E002B9BA3 /* PBXTextBookmark */ = {
  167 + isa = PBXTextBookmark;
  168 + fRef = C901793F11E13174002B9BA3 /* UIImage+ProportionalFill.h */;
  169 + name = "UIImage+ProportionalFill.h: 5";
  170 + rLen = 0;
  171 + rLoc = 116;
  172 + rType = 0;
  173 + vrLen = 765;
  174 + vrLoc = 0;
  175 + };
  176 + C901798611E13A73002B9BA3 /* PBXBookmark */ = {
  177 + isa = PBXBookmark;
  178 + fRef = C901797911E1398F002B9BA3 /* original.png */;
  179 + };
  180 + C901798911E13A73002B9BA3 /* PBXTextBookmark */ = {
  181 + isa = PBXTextBookmark;
  182 + fRef = 1D3623240D0F684500981E51 /* MGImageUtilitiesAppDelegate.h */;
  183 + name = "MGImageUtilitiesAppDelegate.h: 6";
  184 + rLen = 0;
  185 + rLoc = 140;
  186 + rType = 0;
  187 + vrLen = 811;
  188 + vrLoc = 0;
  189 + };
  190 + C90179FF11E1424E002B9BA3 /* ReadMe.rtf */ = {
  191 + uiCtxt = {
  192 + sepNavIntBoundsRect = "{{0, 0}, {1028, 993}}";
  193 + sepNavSelRange = "{1916, 0}";
  194 + sepNavVisRect = "{{0, 0}, {1028, 993}}";
  195 + };
  196 + };
  197 + C9017A1311E14592002B9BA3 /* PBXTextBookmark */ = {
  198 + isa = PBXTextBookmark;
  199 + fRef = C901794211E13174002B9BA3 /* UIImage+Tint.m */;
  200 + name = "UIImage+Tint.m: 19";
  201 + rLen = 0;
  202 + rLoc = 426;
  203 + rType = 0;
  204 + vrLen = 1430;
  205 + vrLoc = 0;
  206 + };
  207 + C9017A7F11E14AD6002B9BA3 /* PBXTextBookmark */ = {
  208 + isa = PBXTextBookmark;
  209 + fRef = 1D3623250D0F684500981E51 /* MGImageUtilitiesAppDelegate.m */;
  210 + name = "MGImageUtilitiesAppDelegate.m: 22";
  211 + rLen = 0;
  212 + rLoc = 416;
  213 + rType = 0;
  214 + vrLen = 1620;
  215 + vrLoc = 0;
  216 + };
  217 + C9017A8711E14BC5002B9BA3 /* PBXTextBookmark */ = {
  218 + isa = PBXTextBookmark;
  219 + fRef = C901794011E13174002B9BA3 /* UIImage+ProportionalFill.m */;
  220 + name = "UIImage+ProportionalFill.m: 43";
  221 + rLen = 0;
  222 + rLoc = 1426;
  223 + rType = 0;
  224 + vrLen = 2881;
  225 + vrLoc = 904;
  226 + };
  227 + C9017A8811E14BC5002B9BA3 /* PBXTextBookmark */ = {
  228 + isa = PBXTextBookmark;
  229 + fRef = C901795511E1354F002B9BA3 /* Source Code License.rtf */;
  230 + name = "Source Code License.rtf: 26";
  231 + rLen = 0;
  232 + rLoc = 1588;
  233 + rType = 0;
  234 + vrLen = 4713;
  235 + vrLoc = 0;
  236 + };
  237 + C9D4927E11E1D09400B63B06 /* PBXTextBookmark */ = {
  238 + isa = PBXTextBookmark;
  239 + fRef = C90179FF11E1424E002B9BA3 /* ReadMe.rtf */;
  240 + name = "ReadMe.rtf: 24";
  241 + rLen = 0;
  242 + rLoc = 1916;
  243 + rType = 0;
  244 + vrLen = 1969;
  245 + vrLoc = 0;
  246 + };
  247 + C9D4928011E1D0B600B63B06 /* PBXTextBookmark */ = {
  248 + isa = PBXTextBookmark;
  249 + fRef = C90179FF11E1424E002B9BA3 /* ReadMe.rtf */;
  250 + name = "ReadMe.rtf: 24";
  251 + rLen = 0;
  252 + rLoc = 1916;
  253 + rType = 0;
  254 + vrLen = 1969;
  255 + vrLoc = 0;
  256 + };
  257 +}
1,595 MGImageUtilities.xcodeproj/matt.perspectivev3
... ... @@ -0,0 +1,1595 @@
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
  3 +<plist version="1.0">
  4 +<dict>
  5 + <key>ActivePerspectiveName</key>
  6 + <string>Project</string>
  7 + <key>AllowedModules</key>
  8 + <array>
  9 + <dict>
  10 + <key>BundleLoadPath</key>
  11 + <string></string>
  12 + <key>MaxInstances</key>
  13 + <string>n</string>
  14 + <key>Module</key>
  15 + <string>PBXSmartGroupTreeModule</string>
  16 + <key>Name</key>
  17 + <string>Groups and Files Outline View</string>
  18 + </dict>
  19 + <dict>
  20 + <key>BundleLoadPath</key>
  21 + <string></string>
  22 + <key>MaxInstances</key>
  23 + <string>n</string>
  24 + <key>Module</key>
  25 + <string>PBXNavigatorGroup</string>
  26 + <key>Name</key>
  27 + <string>Editor</string>
  28 + </dict>
  29 + <dict>
  30 + <key>BundleLoadPath</key>
  31 + <string></string>
  32 + <key>MaxInstances</key>
  33 + <string>n</string>
  34 + <key>Module</key>
  35 + <string>XCTaskListModule</string>
  36 + <key>Name</key>
  37 + <string>Task List</string>
  38 + </dict>
  39 + <dict>
  40 + <key>BundleLoadPath</key>
  41 + <string></string>
  42 + <key>MaxInstances</key>
  43 + <string>n</string>
  44 + <key>Module</key>
  45 + <string>XCDetailModule</string>
  46 + <key>Name</key>
  47 + <string>File and Smart Group Detail Viewer</string>
  48 + </dict>
  49 + <dict>
  50 + <key>BundleLoadPath</key>
  51 + <string></string>
  52 + <key>MaxInstances</key>
  53 + <string>1</string>
  54 + <key>Module</key>
  55 + <string>PBXBuildResultsModule</string>
  56 + <key>Name</key>
  57 + <string>Detailed Build Results Viewer</string>
  58 + </dict>
  59 + <dict>
  60 + <key>BundleLoadPath</key>
  61 + <string></string>
  62 + <key>MaxInstances</key>
  63 + <string>1</string>
  64 + <key>Module</key>
  65 + <string>PBXProjectFindModule</string>
  66 + <key>Name</key>
  67 + <string>Project Batch Find Tool</string>
  68 + </dict>
  69 + <dict>
  70 + <key>BundleLoadPath</key>
  71 + <string></string>
  72 + <key>MaxInstances</key>
  73 + <string>n</string>
  74 + <key>Module</key>
  75 + <string>XCProjectFormatConflictsModule</string>
  76 + <key>Name</key>
  77 + <string>Project Format Conflicts List</string>
  78 + </dict>
  79 + <dict>
  80 + <key>BundleLoadPath</key>
  81 + <string></string>
  82 + <key>MaxInstances</key>
  83 + <string>n</string>
  84 + <key>Module</key>
  85 + <string>PBXBookmarksModule</string>
  86 + <key>Name</key>
  87 + <string>Bookmarks Tool</string>
  88 + </dict>
  89 + <dict>
  90 + <key>BundleLoadPath</key>
  91 + <string></string>
  92 + <key>MaxInstances</key>
  93 + <string>n</string>
  94 + <key>Module</key>
  95 + <string>PBXClassBrowserModule</string>
  96 + <key>Name</key>
  97 + <string>Class Browser</string>
  98 + </dict>
  99 + <dict>
  100 + <key>BundleLoadPath</key>
  101 + <string></string>
  102 + <key>MaxInstances</key>
  103 + <string>n</string>
  104 + <key>Module</key>
  105 + <string>PBXCVSModule</string>
  106 + <key>Name</key>
  107 + <string>Source Code Control Tool</string>
  108 + </dict>
  109 + <dict>
  110 + <key>BundleLoadPath</key>
  111 + <string></string>
  112 + <key>MaxInstances</key>
  113 + <string>n</string>
  114 + <key>Module</key>
  115 + <string>PBXDebugBreakpointsModule</string>
  116 + <key>Name</key>
  117 + <string>Debug Breakpoints Tool</string>
  118 + </dict>
  119 + <dict>
  120 + <key>BundleLoadPath</key>
  121 + <string></string>
  122 + <key>MaxInstances</key>
  123 + <string>n</string>
  124 + <key>Module</key>
  125 + <string>XCDockableInspector</string>
  126 + <key>Name</key>
  127 + <string>Inspector</string>
  128 + </dict>
  129 + <dict>
  130 + <key>BundleLoadPath</key>
  131 + <string></string>
  132 + <key>MaxInstances</key>
  133 + <string>n</string>
  134 + <key>Module</key>
  135 + <string>PBXOpenQuicklyModule</string>
  136 + <key>Name</key>
  137 + <string>Open Quickly Tool</string>
  138 + </dict>
  139 + <dict>
  140 + <key>BundleLoadPath</key>
  141 + <string></string>
  142 + <key>MaxInstances</key>
  143 + <string>1</string>
  144 + <key>Module</key>
  145 + <string>PBXDebugSessionModule</string>
  146 + <key>Name</key>
  147 + <string>Debugger</string>
  148 + </dict>
  149 + <dict>
  150 + <key>BundleLoadPath</key>
  151 + <string></string>
  152 + <key>MaxInstances</key>
  153 + <string>1</string>
  154 + <key>Module</key>
  155 + <string>PBXDebugCLIModule</string>
  156 + <key>Name</key>
  157 + <string>Debug Console</string>
  158 + </dict>
  159 + <dict>
  160 + <key>BundleLoadPath</key>
  161 + <string></string>
  162 + <key>MaxInstances</key>
  163 + <string>n</string>
  164 + <key>Module</key>
  165 + <string>XCSnapshotModule</string>
  166 + <key>Name</key>
  167 + <string>Snapshots Tool</string>
  168 + </dict>
  169 + </array>
  170 + <key>BundlePath</key>
  171 + <string>/Developer/Library/PrivateFrameworks/DevToolsInterface.framework/Resources</string>
  172 + <key>Description</key>
  173 + <string>AIODescriptionKey</string>
  174 + <key>DockingSystemVisible</key>
  175 + <false/>
  176 + <key>Extension</key>
  177 + <string>perspectivev3</string>
  178 + <key>FavBarConfig</key>
  179 + <dict>
  180 + <key>PBXProjectModuleGUID</key>
  181 + <string>C966258B0DCB309D000B46A1</string>
  182 + <key>XCBarModuleItemNames</key>
  183 + <dict/>
  184 + <key>XCBarModuleItems</key>
  185 + <array/>
  186 + </dict>
  187 + <key>FirstTimeWindowDisplayed</key>
  188 + <false/>
  189 + <key>Identifier</key>
  190 + <string>com.apple.perspectives.project.defaultV3</string>
  191 + <key>MajorVersion</key>
  192 + <integer>34</integer>
  193 + <key>MinorVersion</key>
  194 + <integer>0</integer>
  195 + <key>Name</key>
  196 + <string>All-In-One</string>
  197 + <key>Notifications</key>
  198 + <array>
  199 + <dict>
  200 + <key>XCObserverAutoDisconnectKey</key>
  201 + <true/>
  202 + <key>XCObserverDefintionKey</key>
  203 + <dict>
  204 + <key>PBXStatusErrorsKey</key>
  205 + <integer>0</integer>
  206 + </dict>
  207 + <key>XCObserverFactoryKey</key>
  208 + <string>XCPerspectivesSpecificationIdentifier</string>
  209 + <key>XCObserverGUIDKey</key>
  210 + <string>XCObserverProjectIdentifier</string>
  211 + <key>XCObserverNotificationKey</key>
  212 + <string>PBXStatusBuildStateMessageNotification</string>
  213 + <key>XCObserverTargetKey</key>
  214 + <string>XCMainBuildResultsModuleGUID</string>
  215 + <key>XCObserverTriggerKey</key>
  216 + <string>awakenModuleWithObserver:</string>
  217 + <key>XCObserverValidationKey</key>
  218 + <dict>
  219 + <key>PBXStatusErrorsKey</key>
  220 + <integer>2</integer>
  221 + </dict>
  222 + </dict>
  223 + <dict>
  224 + <key>XCObserverAutoDisconnectKey</key>
  225 + <true/>
  226 + <key>XCObserverDefintionKey</key>
  227 + <dict>
  228 + <key>PBXStatusWarningsKey</key>
  229 + <integer>0</integer>
  230 + </dict>
  231 + <key>XCObserverFactoryKey</key>
  232 + <string>XCPerspectivesSpecificationIdentifier</string>
  233 + <key>XCObserverGUIDKey</key>
  234 + <string>XCObserverProjectIdentifier</string>
  235 + <key>XCObserverNotificationKey</key>
  236 + <string>PBXStatusBuildStateMessageNotification</string>
  237 + <key>XCObserverTargetKey</key>
  238 + <string>XCMainBuildResultsModuleGUID</string>
  239 + <key>XCObserverTriggerKey</key>
  240 + <string>awakenModuleWithObserver:</string>
  241 + <key>XCObserverValidationKey</key>
  242 + <dict>
  243 + <key>PBXStatusWarningsKey</key>
  244 + <integer>2</integer>
  245 + </dict>
  246 + </dict>
  247 + <dict>
  248 + <key>XCObserverAutoDisconnectKey</key>
  249 + <true/>
  250 + <key>XCObserverDefintionKey</key>
  251 + <dict>
  252 + <key>PBXStatusAnalyzerResultsKey</key>
  253 + <integer>0</integer>
  254 + </dict>
  255 + <key>XCObserverFactoryKey</key>
  256 + <string>XCPerspectivesSpecificationIdentifier</string>
  257 + <key>XCObserverGUIDKey</key>
  258 + <string>XCObserverProjectIdentifier</string>
  259 + <key>XCObserverNotificationKey</key>
  260 + <string>PBXStatusBuildStateMessageNotification</string>
  261 + <key>XCObserverTargetKey</key>
  262 + <string>XCMainBuildResultsModuleGUID</string>
  263 + <key>XCObserverTriggerKey</key>
  264 + <string>awakenModuleWithObserver:</string>
  265 + <key>XCObserverValidationKey</key>
  266 + <dict>
  267 + <key>PBXStatusAnalyzerResultsKey</key>
  268 + <integer>2</integer>
  269 + </dict>
  270 + </dict>
  271 + </array>
  272 + <key>OpenEditors</key>
  273 + <array/>
  274 + <key>PerspectiveWidths</key>
  275 + <array>
  276 + <integer>1435</integer>
  277 + <integer>1435</integer>
  278 + </array>
  279 + <key>Perspectives</key>
  280 + <array>
  281 + <dict>
  282 + <key>ChosenToolbarItems</key>
  283 + <array>
  284 + <string>XCToolbarPerspectiveControl</string>
  285 + <string>NSToolbarSeparatorItem</string>
  286 + <string>get-info</string>
  287 + <string>active-combo-popup</string>
  288 + <string>action</string>
  289 + <string>NSToolbarFlexibleSpaceItem</string>
  290 + <string>buildOrClean</string>
  291 + <string>debugger-enable-breakpoints</string>
  292 + <string>build-and-go</string>
  293 + <string>servicesModuledebug</string>
  294 + <string>com.apple.ide.PBXToolbarStopButton</string>
  295 + <string>clean</string>
  296 + <string>NSToolbarFlexibleSpaceItem</string>
  297 + <string>com.apple.pbx.toolbar.searchfield</string>
  298 + </array>
  299 + <key>ControllerClassBaseName</key>
  300 + <string></string>
  301 + <key>IconName</key>
  302 + <string>WindowOfProject</string>
  303 + <key>Identifier</key>
  304 + <string>perspective.project</string>
  305 + <key>IsVertical</key>
  306 + <false/>
  307 + <key>Layout</key>
  308 + <array>
  309 + <dict>
  310 + <key>ContentConfiguration</key>
  311 + <dict>
  312 + <key>PBXBottomSmartGroupGIDs</key>
  313 + <array>
  314 + <string>1C37FBAC04509CD000000102</string>
  315 + <string>1C37FAAC04509CD000000102</string>
  316 + <string>1C37FABC05509CD000000102</string>
  317 + <string>1C37FABC05539CD112110102</string>
  318 + <string>1C37FABC04509CD000100104</string>
  319 + <string>1CC0EA4004350EF90044410B</string>
  320 + <string>1CC0EA4004350EF90041110B</string>
  321 + </array>
  322 + <key>PBXProjectModuleGUID</key>
  323 + <string>1CA23ED40692098700951B8B</string>
  324 + <key>PBXProjectModuleLabel</key>
  325 + <string>Files</string>
  326 + <key>PBXProjectStructureProvided</key>
  327 + <string>yes</string>
  328 + <key>PBXSmartGroupTreeModuleColumnData</key>
  329 + <dict>
  330 + <key>PBXSmartGroupTreeModuleColumnWidthsKey</key>
  331 + <array>
  332 + <real>22</real>
  333 + <real>208</real>
  334 + <real>43</real>
  335 + <real>43</real>
  336 + <real>22</real>
  337 + </array>
  338 + <key>PBXSmartGroupTreeModuleColumnsKey_v4</key>
  339 + <array>
  340 + <string>SCMStatusColumn</string>
  341 + <string>MainColumn</string>
  342 + <string>WarningsColumn</string>
  343 + <string>ErrorsColumn</string>
  344 + <string>TargetStatusColumn</string>
  345 + </array>
  346 + </dict>
  347 + <key>PBXSmartGroupTreeModuleOutlineStateKey_v7</key>
  348 + <dict>
  349 + <key>PBXSmartGroupTreeModuleOutlineStateExpansionKey</key>
  350 + <array>
  351 + <string>29B97314FDCFA39411CA2CEA</string>
  352 + <string>080E96DDFE201D6D7F000001</string>
  353 + <string>C901792E11E13130002B9BA3</string>
  354 + <string>C901793111E13134002B9BA3</string>
  355 + <string>29B97317FDCFA39411CA2CEA</string>
  356 + </array>
  357 + <key>PBXSmartGroupTreeModuleOutlineStateSelectionKey</key>
  358 + <array>
  359 + <array>
  360 + <integer>1</integer>
  361 + <integer>0</integer>
  362 + </array>
  363 + </array>
  364 + <key>PBXSmartGroupTreeModuleOutlineStateVisibleRectKey</key>
  365 + <string>{{0, 0}, {338, 997}}</string>
  366 + </dict>
  367 + <key>PBXTopSmartGroupGIDs</key>
  368 + <array/>
  369 + <key>XCIncludePerspectivesSwitch</key>
  370 + <false/>
  371 + </dict>
  372 + <key>GeometryConfiguration</key>
  373 + <dict>
  374 + <key>Frame</key>
  375 + <string>{{0, 0}, {355, 1015}}</string>
  376 + <key>GroupTreeTableConfiguration</key>
  377 + <array>
  378 + <string>SCMStatusColumn</string>
  379 + <real>22</real>
  380 + <string>MainColumn</string>
  381 + <real>208</real>
  382 + <string>WarningsColumn</string>
  383 + <real>43</real>
  384 + <string>ErrorsColumn</string>
  385 + <real>43</real>
  386 + <string>TargetStatusColumn</string>
  387 + <real>22</real>
  388 + </array>
  389 + <key>RubberWindowFrame</key>
  390 + <string>-1448 106 1435 1056 -1920 0 1920 1200 </string>
  391 + </dict>
  392 + <key>Module</key>
  393 + <string>PBXSmartGroupTreeModule</string>
  394 + <key>Proportion</key>
  395 + <string>355pt</string>
  396 + </dict>
  397 + <dict>
  398 + <key>Dock</key>
  399 + <array>
  400 + <dict>
  401 + <key>BecomeActive</key>
  402 + <true/>
  403 + <key>ContentConfiguration</key>
  404 + <dict>
  405 + <key>PBXProjectModuleGUID</key>
  406 + <string>C966256D0DCB2F14000B46A1</string>
  407 + <key>PBXProjectModuleLabel</key>
  408 + <string>ReadMe.rtf</string>
  409 + <key>PBXSplitModuleInNavigatorKey</key>
  410 + <dict>
  411 + <key>Split0</key>
  412 + <dict>
  413 + <key>PBXProjectModuleGUID</key>
  414 + <string>C966256E0DCB2F14000B46A1</string>
  415 + <key>PBXProjectModuleLabel</key>
  416 + <string>ReadMe.rtf</string>
  417 + <key>_historyCapacity</key>
  418 + <integer>0</integer>
  419 + <key>bookmark</key>
  420 + <string>C9D4928011E1D0B600B63B06</string>
  421 + <key>history</key>
  422 + <array>
  423 + <string>C901795811E1357E002B9BA3</string>
  424 + <string>C901795A11E1357E002B9BA3</string>
  425 + <string>C901798611E13A73002B9BA3</string>
  426 + <string>C901798911E13A73002B9BA3</string>
  427 + <string>C9017A1311E14592002B9BA3</string>
  428 + <string>C9017A7F11E14AD6002B9BA3</string>
  429 + <string>C9017A8711E14BC5002B9BA3</string>
  430 + <string>C9017A8811E14BC5002B9BA3</string>
  431 + <string>C9D4927E11E1D09400B63B06</string>
  432 + </array>
  433 + </dict>
  434 + <key>SplitCount</key>
  435 + <string>1</string>
  436 + </dict>
  437 + <key>StatusBarVisibility</key>
  438 + <true/>
  439 + <key>XCSharingToken</key>
  440 + <string>com.apple.Xcode.CommonNavigatorGroupSharingToken</string>
  441 + </dict>
  442 + <key>GeometryConfiguration</key>
  443 + <dict>
  444 + <key>Frame</key>
  445 + <string>{{0, 0}, {1075, 1010}}</string>
  446 + <key>RubberWindowFrame</key>
  447 + <string>-1448 106 1435 1056 -1920 0 1920 1200 </string>
  448 + </dict>
  449 + <key>Module</key>
  450 + <string>PBXNavigatorGroup</string>
  451 + <key>Proportion</key>
  452 + <string>1010pt</string>
  453 + </dict>
  454 + <dict>
  455 + <key>Proportion</key>
  456 + <string>0pt</string>
  457 + <key>Tabs</key>
  458 + <array>
  459 + <dict>
  460 + <key>ContentConfiguration</key>
  461 + <dict>
  462 + <key>PBXProjectModuleGUID</key>
  463 + <string>1CA23EDF0692099D00951B8B</string>
  464 + <key>PBXProjectModuleLabel</key>
  465 + <string>Detail</string>
  466 + </dict>
  467 + <key>GeometryConfiguration</key>
  468 + <dict>
  469 + <key>Frame</key>
  470 + <string>{{10, 27}, {1075, -27}}</string>
  471 + <key>RubberWindowFrame</key>
  472 + <string>-1448 106 1435 1056 -1920 0 1920 1200 </string>
  473 + </dict>
  474 + <key>Module</key>
  475 + <string>XCDetailModule</string>
  476 + </dict>
  477 + <dict>
  478 + <key>ContentConfiguration</key>
  479 + <dict>
  480 + <key>PBXProjectModuleGUID</key>
  481 + <string>1CA23EE00692099D00951B8B</string>
  482 + <key>PBXProjectModuleLabel</key>
  483 + <string>Project Find</string>
  484 + </dict>
  485 + <key>GeometryConfiguration</key>
  486 + <dict>
  487 + <key>Frame</key>
  488 + <string>{{0, 0}, {614, 336}}</string>
  489 + </dict>
  490 + <key>Module</key>
  491 + <string>PBXProjectFindModule</string>
  492 + </dict>
  493 + <dict>
  494 + <key>ContentConfiguration</key>
  495 + <dict>
  496 + <key>PBXCVSModuleFilterTypeKey</key>
  497 + <integer>1032</integer>
  498 + <key>PBXProjectModuleGUID</key>
  499 + <string>1CA23EE10692099D00951B8B</string>
  500 + <key>PBXProjectModuleLabel</key>
  501 + <string>SCM Results</string>
  502 + </dict>
  503 + <key>GeometryConfiguration</key>
  504 + <dict>
  505 + <key>Frame</key>