Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

- Added NoodleCustomImageRep.

- Added ImageLab example app to demonstrate different aspects of NSImage. Refer to the blog post referenced in the README for more details.
  • Loading branch information...
commit c8f439cbe92c7a86e3386b94510c18d826b1bcb3 1 parent 4e87d65
Paul Kim authored
View
1  Examples/ImageLab/Credits.rtf
View
5,098 Examples/ImageLab/English.lproj/MainMenu.xib
5,098 additions, 0 deletions not shown
View
28 Examples/ImageLab/ImageLab-Info.plist
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>English</string>
+ <key>CFBundleExecutable</key>
+ <string>${EXECUTABLE_NAME}</string>
+ <key>CFBundleIdentifier</key>
+ <string>com.yourcompany.${PRODUCT_NAME:rfc1034identifier}</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundlePackageType</key>
+ <string>APPL</string>
+ <key>CFBundleShortVersionString</key>
+ <string>1.0</string>
+ <key>CFBundleSignature</key>
+ <string>????</string>
+ <key>CFBundleVersion</key>
+ <string>1</string>
+ <key>LSMinimumSystemVersion</key>
+ <string>${MACOSX_DEPLOYMENT_TARGET}</string>
+ <key>NSMainNibFile</key>
+ <string>MainMenu</string>
+ <key>NSPrincipalClass</key>
+ <string>NSApplication</string>
+</dict>
+</plist>
View
45 Examples/ImageLab/ImageLabAppDelegate.h
@@ -0,0 +1,45 @@
+//
+// ImageLabAppDelegate.h
+// ImageLab
+//
+// Created by Paul Kim on 3/20/11.
+// Copyright 2011 Noodlesoft, LLC. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+
+#import <Cocoa/Cocoa.h>
+
+@interface ImageLabAppDelegate : NSObject <NSApplicationDelegate>
+{
+ IBOutlet NSImageView *imageView;
+ IBOutlet NSTextField *timeLabel;
+ IBOutlet NSButton *recacheIndicator;
+ NSImage *testImage;
+ NSWindow *window;
+}
+
+@property (assign) IBOutlet NSWindow *window;
+
+- (IBAction)switchImage:sender;
+- (IBAction)redraw:sender;
+
+@end
View
256 Examples/ImageLab/ImageLabAppDelegate.m
@@ -0,0 +1,256 @@
+//
+// ImageLabAppDelegate.m
+// ImageLab
+//
+// Created by Paul Kim on 3/20/11.
+// Copyright 2011 Noodlesoft, LLC. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+
+#import "ImageLabAppDelegate.h"
+#import "NoodleCustomImageRep.h"
+#import <QuartzCore/QuartzCore.h>
+
+@implementation ImageLabAppDelegate
+
+@synthesize window;
+
+- (NSImage *)lockFocusImage
+{
+ NSImage *image;
+ NSSize size;
+ CGFloat diameter;
+
+ image = [[testImage copy] autorelease];
+
+ size = [image size];
+ diameter = size.width / 2.0;
+
+ [image lockFocus];
+
+ [[NSColor blackColor] set];
+ [[NSBezierPath bezierPathWithOvalInRect:NSMakeRect(diameter / 2.0, diameter / 2.0, diameter, diameter)] fill];
+
+ [image unlockFocus];
+
+ return image;
+}
+
+- (NSImage *)customRepImage
+{
+ NoodleCustomImageRep *rep;
+ NSSize size;
+ NSImage *image;
+
+ size = [testImage size];
+
+ rep = [NoodleCustomImageRep imageRepWithDrawBlock:
+ ^(NoodleCustomImageRep *blockRep)
+ {
+ NSSize repSize;
+ CGFloat diameter;
+
+ repSize = [blockRep size];
+ diameter = repSize.width / 2.0;
+
+ [testImage drawInRect:NSMakeRect(0.0, 0.0, size.width, size.height) fromRect:NSZeroRect operation:NSCompositeCopy fraction:1.0];
+
+ [[NSColor blackColor] set];
+ [[NSBezierPath bezierPathWithOvalInRect:NSMakeRect(diameter / 2.0, diameter / 2.0, diameter, diameter)] fill];
+
+ [recacheIndicator setImage:[[[NSImage imageNamed:NSImageNameStatusAvailable] copy] autorelease]];
+ }];
+ [rep setSize:size];
+ image = [[[NSImage alloc] initWithSize:size] autorelease];
+ [image addRepresentation:rep];
+
+ return image;
+}
+
+- (NSImage *)lockFocusDrawnImage
+{
+ NSImage *image;
+ NSSize size;
+
+ size = NSMakeSize(10.0, 10.0);
+
+ image = [[[NSImage alloc] initWithSize:size] autorelease];
+
+ [image lockFocus];
+
+ [[NSGraphicsContext currentContext] setShouldAntialias:NO];
+
+ [[NSColor blueColor] set];
+ NSRectFill(NSMakeRect(1.0, 1.0, 8.0, 8.0));
+
+ [image unlockFocus];
+ return image;
+}
+
+- (NSImage *)customRepDrawnImage
+{
+ NoodleCustomImageRep *rep;
+ NSSize size;
+ NSImage *image;
+
+ size = NSMakeSize(10.0, 10.0);
+
+ rep = [NoodleCustomImageRep imageRepWithDrawBlock:
+ ^(NoodleCustomImageRep *blockRep)
+ {
+ [[NSColor blueColor] set];
+ NSRectFill(NSMakeRect(1.0, 1.0, 8.0, 8.0));
+
+ [recacheIndicator setImage:[[[NSImage imageNamed:NSImageNameStatusAvailable] copy] autorelease]];
+ }];
+ [rep setSize:size];
+ image = [[[NSImage alloc] initWithSize:size] autorelease];
+ [image addRepresentation:rep];
+
+ return image;
+}
+
+- (NSImage *)coreImageTIFFRep
+{
+ NSImage *image;
+ NSSize size;
+ CIImage *input, *output;
+ CIFilter *filter;
+ NSCIImageRep *rep;
+ CGRect extent;
+ CGAffineTransform transform;
+
+ size = [testImage size];
+
+ input = [CIImage imageWithData:[testImage TIFFRepresentation]];
+ filter = [CIFilter filterWithName:@"CIPointillize" keysAndValues:
+ @"inputImage", input,
+ @"inputRadius", [NSNumber numberWithFloat:(float)(size.width / 10.0)],
+ @"inputCenter", [CIVector vectorWithX:size.width / 2.0 Y:size.height / 2.0],
+ nil];
+ output = [filter valueForKey:@"outputImage"];
+
+ extent = [output extent];
+ transform = CGAffineTransformMakeScale(size.width / extent.size.width, size.height / extent.size.height);
+ transform = CGAffineTransformTranslate(transform, -extent.origin.x, -extent.origin.y);
+ output = [output imageByApplyingTransform:transform];
+
+ image = [[[NSImage alloc] initWithSize:size] autorelease];
+ rep = [NSCIImageRep imageRepWithCIImage:output];
+ [rep setSize:size];
+ [image addRepresentation:rep];
+
+ return image;
+}
+
+- (NSImage *)coreImageCustomImageRep
+{
+ NoodleCustomImageRep *rep;
+ NSSize size;
+ NSImage *image;
+ __block id label;
+
+ label = timeLabel;
+
+ size = [testImage size];
+
+ rep = [NoodleCustomImageRep imageRepWithDrawBlock:
+ ^(NoodleCustomImageRep *blockRep)
+ {
+ CGImageRef cgImage;
+ CIImage *input, *output;
+ CIFilter *filter;
+ NSRect rect;
+
+ rect.origin = NSMakePoint(0.0, 0.0);
+ rect.size = [blockRep size];
+
+ cgImage = [testImage CGImageForProposedRect:&rect
+ context:[NSGraphicsContext currentContext]
+ hints:nil];
+ input = [CIImage imageWithCGImage:cgImage];
+ filter = [CIFilter filterWithName:@"CIPointillize" keysAndValues:
+ @"inputImage", input,
+ @"inputRadius", [NSNumber numberWithFloat:(float)(NSWidth(rect) / 10.0)],
+ @"inputCenter", [CIVector vectorWithX:NSWidth(rect) / 2.0 Y:NSHeight(rect) / 2.0],
+ nil];
+ output = [filter valueForKey:@"outputImage"];
+
+ [output drawInRect:rect fromRect:NSRectFromCGRect([output extent]) operation:NSCompositeCopy fraction:1.0];
+
+ [recacheIndicator setImage:[[[NSImage imageNamed:NSImageNameStatusAvailable] copy] autorelease]];
+ }];
+
+ [rep setSize:size];
+ image = [[[NSImage alloc] initWithSize:size] autorelease];
+ [image addRepresentation:rep];
+
+ return image;
+}
+
+
+- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
+{
+ testImage = [[NSImage imageNamed:@"test"] copy];
+ [recacheIndicator setImage:[[[NSImage imageNamed:NSImageNameStatusNone] copy] autorelease]];
+}
+
+- (IBAction)switchImage:(id)sender
+{
+ NSInteger tag;
+ NSImage *image;
+
+ tag = [sender selectedTag];
+
+ switch (tag)
+ {
+ case 0:
+ image = testImage;
+ break;
+ case 1:
+ image = [self lockFocusImage];
+ break;
+ case 2:
+ image = [self customRepImage];
+ break;
+ case 3:
+ image = [self lockFocusDrawnImage];
+ break;
+ case 4:
+ image = [self customRepDrawnImage];
+ break;
+ case 5:
+ image = [self coreImageTIFFRep];
+ break;
+ case 6:
+ image = [self coreImageCustomImageRep];
+ break;
+ }
+ [imageView setObjectValue:image];
+}
+
+- (IBAction)redraw:sender
+{
+ [imageView display];
+}
+
+@end
View
78 Examples/ImageLab/Read Me.rtf
@@ -0,0 +1,78 @@
+{\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf350
+{\fonttbl\f0\fswiss\fcharset0 Helvetica;\f1\fnil\fcharset0 Monaco;}
+{\colortbl;\red255\green255\blue255;}
+{\*\listtable{\list\listtemplateid1\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{disc\}}{\leveltext\leveltemplateid1\'01\uc0\u8226 ;}{\levelnumbers;}\fi-360\li720\lin720 }{\listname ;}\listid1}
+{\list\listtemplateid2\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{disc\}}{\leveltext\leveltemplateid101\'01\uc0\u8226 ;}{\levelnumbers;}\fi-360\li720\lin720 }{\listname ;}\listid2}}
+{\*\listoverridetable{\listoverride\listid1\listoverridecount0\ls1}{\listoverride\listid2\listoverridecount0\ls2}}
+\margl1440\margr1440\vieww19360\viewh15600\viewkind0
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural
+
+\f0\b\fs24 \cf0 ImageLab
+\b0 \
+\
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural\pardirnatural
+\cf0 \
+This is a sample program that is a companion piece to my blog article on NSImage here: {\field{\*\fldinst{HYPERLINK "http://www.noodlesoft.com/blog/2011/04/15/the-proper-care-and-feeding-of-nsimage"}}{\fldrslt http://www.noodlesoft.com/blog/2011/04/15/the-proper-care-and-feeding-of-nsimage}}\
+\
+This program shows different ways, both good and bad, of using NSImage. Please see the companion article as it goes into much more detail. This project also demonstrates use of NoodleCustomImageRep.\
+\
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural\pardirnatural
+
+\b \cf0 Notes
+\b0 \
+\pard\tx220\tx720\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\li720\fi-720\ql\qnatural\pardirnatural
+\ls1\ilvl0\cf0 \
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural\pardirnatural
+\cf0 \
+\
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural\pardirnatural
+
+\b \cf0 Possible Improvements\
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural\pardirnatural
+
+\b0 \cf0 \
+\
+\
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural\pardirnatural
+
+\b \cf0 Contact
+\b0 \
+\
+Just go {\field{\*\fldinst{HYPERLINK "http://www.noodlesoft.com/about.php"}}{\fldrslt www.noodlesoft.com}} and shoot me an email. Or visit the blog article linked above and leave a comment. Bugs, suggestions and other feedback appreciated.\
+\
+\
+
+\b License
+\b0 \
+\
+I am releasing this under the MIT license.\
+\
+____________________________________\
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural\pardirnatural
+
+\f1 \cf0 Copyright (c) 2011 Noodlesoft, LLC. All Rights Reserved.\
+\
+Permission is hereby granted, free of charge, to any person\
+obtaining a copy of this software and associated documentation\
+files (the "Software"), to deal in the Software without\
+restriction, including without limitation the rights to use,\
+copy, modify, merge, publish, distribute, sublicense, and/or sell\
+copies of the Software, and to permit persons to whom the\
+Software is furnished to do so, subject to the following\
+conditions:\
+\
+The above copyright notice and this permission notice shall be\
+included in all copies or substantial portions of the Software.\
+\
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES\
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\
+OTHER DEALINGS IN THE SOFTWARE.\
+\pard\tx220\tx720\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\li720\fi-720\ql\qnatural\pardirnatural
+\ls2\ilvl0
+\f0\b \cf0 \
+}
View
39 Examples/ImageLab/TimedImageView.h
@@ -0,0 +1,39 @@
+//
+// TimedImageView.h
+// ImageLab
+//
+// Created by Paul Kim on 3/20/11.
+// Copyright 2011 Noodlesoft, LLC. All rights reserved.
+//
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+
+#import <Cocoa/Cocoa.h>
+
+
+@interface TimedImageView : NSImageView
+{
+ IBOutlet id label;
+ IBOutlet id redrawIndicator;
+}
+
+@end
View
54 Examples/ImageLab/TimedImageView.m
@@ -0,0 +1,54 @@
+//
+// TimedImageView.m
+// ImageLab
+//
+// Created by Paul Kim on 3/20/11.
+// Copyright 2011 Noodlesoft, LLC. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+
+#import "TimedImageView.h"
+
+
+@implementation TimedImageView
+
+- (void)updateLabel:(NSTimeInterval)time
+{
+ [label setStringValue:[NSString stringWithFormat:@"%.2f ms", time]];
+}
+
+- (void)drawRect:(NSRect)rect
+{
+ NSTimeInterval time, diff;
+
+ [redrawIndicator setImage:[[[NSImage imageNamed:NSImageNameStatusNone] copy] autorelease]];
+
+ time = [NSDate timeIntervalSinceReferenceDate];
+
+ [super drawRect:rect];
+
+ diff = [NSDate timeIntervalSinceReferenceDate] - time;
+
+ [self updateLabel:diff * 1000];
+}
+
+@end
View
14 Examples/ImageLab/main.m
@@ -0,0 +1,14 @@
+//
+// main.m
+// ImageLab
+//
+// Created by Paul Kim on 3/20/11.
+// Copyright 2011 Noodlesoft, LLC. All rights reserved.
+//
+
+#import <Cocoa/Cocoa.h>
+
+int main(int argc, char *argv[])
+{
+ return NSApplicationMain(argc, (const char **) argv);
+}
View
BIN  Examples/ImageLab/test.tiff
Binary file not shown
View
49 NoodleCustomImageRep.h
@@ -0,0 +1,49 @@
+//
+// NoodleCustomImageRep.h
+// NoodleKit
+//
+// Created by Paul Kim on 3/16/11.
+// Copyright 2011 Noodlesoft, LLC. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+
+#import <Cocoa/Cocoa.h>
+
+@class NoodleCustomImageRep;
+
+/*
+ This image rep just provides a way to specify the image drawing via a block.
+
+ For more details, check out the related blog post at http://www.noodlesoft.com/blog/2011/04/15/the-proper-care-and-feeding-of-nsimage
+ */
+@interface NoodleCustomImageRep : NSImageRep
+{
+ void (^_drawBlock)(NoodleCustomImageRep *);
+}
+
+@property (readwrite, copy) void (^drawBlock)(NoodleCustomImageRep *rep);
+
++ (id)imageRepWithDrawBlock:(void (^)(NoodleCustomImageRep *))block;
+
+- (id)initWithDrawBlock:(void (^)(NoodleCustomImageRep *))block;
+
+@end
View
64 NoodleCustomImageRep.m
@@ -0,0 +1,64 @@
+//
+// NoodleCustomImageRep.m
+// ImageCacheTest
+//
+// Created by Paul Kim on 3/16/11.
+// Copyright 2011 Noodlesoft, LLC. All rights reserved.
+//
+
+#import "NoodleCustomImageRep.h"
+
+
+@implementation NoodleCustomImageRep
+
+@synthesize drawBlock = _drawBlock;
+
++ (id)imageRepWithDrawBlock:(void (^)(NoodleCustomImageRep *))block
+{
+ return [[[[self class] alloc] initWithDrawBlock:block] autorelease];
+}
+
+- (id)initWithDrawBlock:(void (^)(NoodleCustomImageRep *))block
+{
+ if ((self = [super init]) != nil)
+ {
+ [self setDrawBlock:block];
+ }
+ return self;
+}
+
+#pragma mark NSCopying method
+
+- (id)copyWithZone:(NSZone *)zone
+{
+ NoodleCustomImageRep *copy;
+
+ copy = [super copyWithZone:zone];
+
+ // NSImageRep uses NSCopyObject so we have to force a copy here
+ copy->_drawBlock = [_drawBlock copy];
+
+ return copy;
+}
+
+- (void)dealloc
+{
+ [self setDrawBlock:nil];
+
+ [super dealloc];
+}
+
+#pragma mark NSImageRep methods
+
+- (BOOL)draw
+{
+ if (_drawBlock != NULL)
+ {
+ _drawBlock(self);
+
+ return YES;
+ }
+ return NO;
+}
+
+@end
View
184 NoodleKit.xcodeproj/project.pbxproj
@@ -73,6 +73,17 @@
327CD86A11DD237000A88EA5 /* NoodleKit.framework in Copy Frameworks */ = {isa = PBXBuildFile; fileRef = 8DC2EF5B0486A6940098B216 /* NoodleKit.framework */; };
8DC2EF530486A6940098B216 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 089C1666FE841158C02AAC07 /* InfoPlist.strings */; };
8DC2EF570486A6940098B216 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7B1FEA5585E11CA2CBB /* Cocoa.framework */; };
+ B40F77FC135527AE00FCC42A /* NoodleCustomImageRep.h in Headers */ = {isa = PBXBuildFile; fileRef = B40F77FA135527AE00FCC42A /* NoodleCustomImageRep.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ B40F77FD135527AE00FCC42A /* NoodleCustomImageRep.m in Sources */ = {isa = PBXBuildFile; fileRef = B40F77FB135527AE00FCC42A /* NoodleCustomImageRep.m */; };
+ B40F780F13552B0B00FCC42A /* NoodleKit.framework in Copy Frameworks */ = {isa = PBXBuildFile; fileRef = 8DC2EF5B0486A6940098B216 /* NoodleKit.framework */; };
+ B40F782A13552B7100FCC42A /* NoodleKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8DC2EF5B0486A6940098B216 /* NoodleKit.framework */; };
+ B40F784C13562C4D00FCC42A /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = B40F784A13562C4D00FCC42A /* MainMenu.xib */; };
+ B40F785113562CA500FCC42A /* test.tiff in Resources */ = {isa = PBXBuildFile; fileRef = B40F785013562CA500FCC42A /* test.tiff */; };
+ B40F785513562CED00FCC42A /* ImageLabAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = B40F785413562CED00FCC42A /* ImageLabAppDelegate.m */; };
+ B40F786113562D8C00FCC42A /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B40F786013562D8C00FCC42A /* QuartzCore.framework */; };
+ B40F786A13562DCF00FCC42A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = B40F786913562DCF00FCC42A /* main.m */; };
+ B40F788113562E5000FCC42A /* TimedImageView.m in Sources */ = {isa = PBXBuildFile; fileRef = B40F788013562E5000FCC42A /* TimedImageView.m */; };
+ B40F78AA1356317F00FCC42A /* Credits.rtf in Resources */ = {isa = PBXBuildFile; fileRef = B40F78A91356317F00FCC42A /* Credits.rtf */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
@@ -118,6 +129,13 @@
remoteGlobalIDString = 8DC2EF4F0486A6940098B216;
remoteInfo = NoodleKit;
};
+ B40F781413552B1B00FCC42A /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 0867D690FE84028FC02AAC07 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 8DC2EF4F0486A6940098B216;
+ remoteInfo = NoodleKit;
+ };
/* End PBXContainerItemProxy section */
/* Begin PBXCopyFilesBuildPhase section */
@@ -187,6 +205,17 @@
name = "Copy Frameworks";
runOnlyForDeploymentPostprocessing = 0;
};
+ B40F784813552B8700FCC42A /* Copy Frameworks */ = {
+ isa = PBXCopyFilesBuildPhase;
+ buildActionMask = 2147483647;
+ dstPath = "";
+ dstSubfolderSpec = 10;
+ files = (
+ B40F780F13552B0B00FCC42A /* NoodleKit.framework in Copy Frameworks */,
+ );
+ name = "Copy Frameworks";
+ runOnlyForDeploymentPostprocessing = 0;
+ };
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
@@ -264,6 +293,19 @@
32DBCF5E0370ADEE00C91783 /* NoodleKit_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NoodleKit_Prefix.pch; sourceTree = "<group>"; };
8DC2EF5A0486A6940098B216 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
8DC2EF5B0486A6940098B216 /* NoodleKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = NoodleKit.framework; sourceTree = BUILT_PRODUCTS_DIR; };
+ B40F77FA135527AE00FCC42A /* NoodleCustomImageRep.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NoodleCustomImageRep.h; sourceTree = "<group>"; };
+ B40F77FB135527AE00FCC42A /* NoodleCustomImageRep.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NoodleCustomImageRep.m; sourceTree = "<group>"; };
+ B40F780913552AF900FCC42A /* ImageLab.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ImageLab.app; sourceTree = BUILT_PRODUCTS_DIR; };
+ B40F780B13552AF900FCC42A /* ImageLab-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "ImageLab-Info.plist"; sourceTree = "<group>"; };
+ B40F784B13562C4D00FCC42A /* English */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = English; path = English.lproj/MainMenu.xib; sourceTree = "<group>"; };
+ B40F785013562CA500FCC42A /* test.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = test.tiff; sourceTree = "<group>"; };
+ B40F785313562CED00FCC42A /* ImageLabAppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ImageLabAppDelegate.h; sourceTree = "<group>"; };
+ B40F785413562CED00FCC42A /* ImageLabAppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ImageLabAppDelegate.m; sourceTree = "<group>"; };
+ B40F786013562D8C00FCC42A /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; };
+ B40F786913562DCF00FCC42A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
+ B40F787F13562E5000FCC42A /* TimedImageView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TimedImageView.h; sourceTree = "<group>"; };
+ B40F788013562E5000FCC42A /* TimedImageView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TimedImageView.m; sourceTree = "<group>"; };
+ B40F78A91356317F00FCC42A /* Credits.rtf */ = {isa = PBXFileReference; lastKnownFileType = text.rtf; path = Credits.rtf; sourceTree = "<group>"; };
D2F7E79907B2D74100F64583 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = /System/Library/Frameworks/CoreData.framework; sourceTree = "<absolute>"; };
/* End PBXFileReference section */
@@ -328,6 +370,15 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
+ B40F780713552AF900FCC42A /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ B40F782A13552B7100FCC42A /* NoodleKit.framework in Frameworks */,
+ B40F786113562D8C00FCC42A /* QuartzCore.framework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
@@ -341,6 +392,7 @@
322DEBA61072593A00CB7080 /* Window Effects.app */,
3251D22F108F800C007E281D /* iToonz.app */,
327CD76911DCF2EE00A88EA5 /* TimerLab.app */,
+ B40F780913552AF900FCC42A /* ImageLab.app */,
);
name = Products;
sourceTree = "<group>";
@@ -354,6 +406,7 @@
0867D69AFE84028FC02AAC07 /* External Frameworks and Libraries */,
3278307F1071513F0041F09C /* Examples */,
034768DFFF38A50411DB9C8B /* Products */,
+ B40F786013562D8C00FCC42A /* QuartzCore.framework */,
);
name = NoodleKit;
sourceTree = "<group>";
@@ -391,6 +444,8 @@
327CD73611DCF15200A88EA5 /* NoodleGlue.m */,
32782FDC10713DA00041F09C /* NSImage-NoodleExtensions.h */,
32782FDD10713DA00041F09C /* NSImage-NoodleExtensions.m */,
+ B40F77FA135527AE00FCC42A /* NoodleCustomImageRep.h */,
+ B40F77FB135527AE00FCC42A /* NoodleCustomImageRep.m */,
32783038107140600041F09C /* NSWindow-NoodleEffects.h */,
32783039107140600041F09C /* NSWindow-NoodleEffects.m */,
32782FB410713B640041F09C /* NoodleLineNumberMarker.h */,
@@ -453,6 +508,7 @@
3278307F1071513F0041F09C /* Examples */ = {
isa = PBXGroup;
children = (
+ B40F780013552AD300FCC42A /* ImageLab */,
327CD77811DCF74C00A88EA5 /* TimerLab */,
3251D23E108F8063007E281D /* iToonz */,
327831A110715FC90041F09C /* LineNumberView */,
@@ -525,6 +581,22 @@
name = "Other Sources";
sourceTree = "<group>";
};
+ B40F780013552AD300FCC42A /* ImageLab */ = {
+ isa = PBXGroup;
+ children = (
+ B40F78A91356317F00FCC42A /* Credits.rtf */,
+ B40F786913562DCF00FCC42A /* main.m */,
+ B40F785013562CA500FCC42A /* test.tiff */,
+ B40F784A13562C4D00FCC42A /* MainMenu.xib */,
+ B40F785313562CED00FCC42A /* ImageLabAppDelegate.h */,
+ B40F785413562CED00FCC42A /* ImageLabAppDelegate.m */,
+ B40F787F13562E5000FCC42A /* TimedImageView.h */,
+ B40F788013562E5000FCC42A /* TimedImageView.m */,
+ B40F780B13552AF900FCC42A /* ImageLab-Info.plist */,
+ );
+ path = ImageLab;
+ sourceTree = "<group>";
+ };
/* End PBXGroup section */
/* Begin PBXHeadersBuildPhase section */
@@ -544,6 +616,7 @@
3251D225108F7FB9007E281D /* NoodleTableView.h in Headers */,
3251D48D1090FFB0007E281D /* NSTableView-NoodleExtensions.h in Headers */,
326A35061092486800AF02F8 /* NoodleIPhoneTableView.h in Headers */,
+ B40F77FC135527AE00FCC42A /* NoodleCustomImageRep.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -683,6 +756,25 @@
productReference = 8DC2EF5B0486A6940098B216 /* NoodleKit.framework */;
productType = "com.apple.product-type.framework";
};
+ B40F780813552AF900FCC42A /* ImageLab */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = B40F780E13552AFA00FCC42A /* Build configuration list for PBXNativeTarget "ImageLab" */;
+ buildPhases = (
+ B40F780513552AF900FCC42A /* Resources */,
+ B40F780613552AF900FCC42A /* Sources */,
+ B40F780713552AF900FCC42A /* Frameworks */,
+ B40F784813552B8700FCC42A /* Copy Frameworks */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ B40F781513552B1B00FCC42A /* PBXTargetDependency */,
+ );
+ name = ImageLab;
+ productName = ImageLab;
+ productReference = B40F780913552AF900FCC42A /* ImageLab.app */;
+ productType = "com.apple.product-type.application";
+ };
/* End PBXNativeTarget section */
/* Begin PBXProject section */
@@ -710,6 +802,7 @@
322DEBA51072593A00CB7080 /* Window Effects */,
3251D22E108F800C007E281D /* iToonz */,
327CD76811DCF2EE00A88EA5 /* TimerLab */,
+ B40F780813552AF900FCC42A /* ImageLab */,
);
};
/* End PBXProject section */
@@ -776,6 +869,16 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
+ B40F780513552AF900FCC42A /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ B40F784C13562C4D00FCC42A /* MainMenu.xib in Resources */,
+ B40F785113562CA500FCC42A /* test.tiff in Resources */,
+ B40F78AA1356317F00FCC42A /* Credits.rtf in Resources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
/* End PBXResourcesBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
@@ -850,6 +953,17 @@
3251D226108F7FB9007E281D /* NoodleTableView.m in Sources */,
3251D48E1090FFB0007E281D /* NSTableView-NoodleExtensions.m in Sources */,
326A35051092486400AF02F8 /* NoodleIPhoneTableView.m in Sources */,
+ B40F77FD135527AE00FCC42A /* NoodleCustomImageRep.m in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ B40F780613552AF900FCC42A /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ B40F785513562CED00FCC42A /* ImageLabAppDelegate.m in Sources */,
+ B40F786A13562DCF00FCC42A /* main.m in Sources */,
+ B40F788113562E5000FCC42A /* TimedImageView.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -886,6 +1000,11 @@
target = 8DC2EF4F0486A6940098B216 /* NoodleKit */;
targetProxy = 327CD79111DCF8D500A88EA5 /* PBXContainerItemProxy */;
};
+ B40F781513552B1B00FCC42A /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 8DC2EF4F0486A6940098B216 /* NoodleKit */;
+ targetProxy = B40F781413552B1B00FCC42A /* PBXContainerItemProxy */;
+ };
/* End PBXTargetDependency section */
/* Begin PBXVariantGroup section */
@@ -948,6 +1067,14 @@
name = MainMenu.xib;
sourceTree = "<group>";
};
+ B40F784A13562C4D00FCC42A /* MainMenu.xib */ = {
+ isa = PBXVariantGroup;
+ children = (
+ B40F784B13562C4D00FCC42A /* English */,
+ );
+ name = MainMenu.xib;
+ sourceTree = "<group>";
+ };
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
@@ -1327,6 +1454,54 @@
};
name = Release;
};
+ B40F780C13552AF900FCC42A /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ COPY_PHASE_STRIP = NO;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_ENABLE_FIX_AND_CONTINUE = YES;
+ GCC_MODEL_TUNING = G5;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_PRECOMPILE_PREFIX_HEADER = YES;
+ GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/AppKit.framework/Headers/AppKit.h";
+ INFOPLIST_FILE = "Examples/ImageLab/ImageLab-Info.plist";
+ INSTALL_PATH = "$(HOME)/Applications";
+ OTHER_LDFLAGS = (
+ "-framework",
+ Foundation,
+ "-framework",
+ AppKit,
+ );
+ PREBINDING = NO;
+ PRODUCT_NAME = ImageLab;
+ };
+ name = Debug;
+ };
+ B40F780D13552AF900FCC42A /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ COPY_PHASE_STRIP = YES;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ GCC_ENABLE_FIX_AND_CONTINUE = NO;
+ GCC_MODEL_TUNING = G5;
+ GCC_PRECOMPILE_PREFIX_HEADER = YES;
+ GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/AppKit.framework/Headers/AppKit.h";
+ INFOPLIST_FILE = "Examples/ImageLab/ImageLab-Info.plist";
+ INSTALL_PATH = "$(HOME)/Applications";
+ OTHER_LDFLAGS = (
+ "-framework",
+ Foundation,
+ "-framework",
+ AppKit,
+ );
+ PREBINDING = NO;
+ PRODUCT_NAME = ImageLab;
+ ZERO_LINK = NO;
+ };
+ name = Release;
+ };
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
@@ -1402,6 +1577,15 @@
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
+ B40F780E13552AFA00FCC42A /* Build configuration list for PBXNativeTarget "ImageLab" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ B40F780C13552AF900FCC42A /* Debug */,
+ B40F780D13552AF900FCC42A /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
/* End XCConfigurationList section */
};
rootObject = 0867D690FE84028FC02AAC07 /* Project object */;
View
4 README.md
@@ -39,6 +39,10 @@ NSResponder category providing methods that will dismiss a dialog and return the
NSImage category providing methods to draw NSImages with correct orientation and scaling regardless of the flipped status of the image or the context being drawn into.
<http://www.noodlesoft.com/blog/2009/02/02/understanding-flipped-coordinate-systems/>
+#### NoodleCustomImageRep
+NSImageRep subclass that allows you to specify the drawing via a block. Handy for drawing images without having to create a new subclass of NSImageRep.
+<http://www.noodlesoft.com/blog/2011/04/15/the-proper-care-and-feeding-of-nsimage>
+
#### NSWindow-NoodleEffects
Provides a basic zoom effect for NSWindow.
<http://www.noodlesoft.com/blog/2007/06/30/animation-in-the-time-of-tiger-part-1/>

0 comments on commit c8f439c

Please sign in to comment.
Something went wrong with that request. Please try again.