julius / showcase

Quicksilver Interface

This URL has Read+Write access

showcase / NSImage-Extra.m
100644 326 lines (262 sloc) 11.809 kb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
//
// NSImage-Extra.m
// SmallGame
//
// Created by Julius Eckert on 21.12.07.
// Copyright 2007 __MyCompanyName__. All rights reserved.
//
 
#import "NSImage-Extra.h"
 
 
@implementation NSImage (Extra)
 
- (CGImageRef) cgImage
{
// I'm open to better ideas. :)
 
NSData* data = [self TIFFRepresentation];
return CreateCGImageFromData(data);
}
 
- (NSSize)proportionalSizeForTargetSize:(NSSize)targetSize
{
    NSSize imageSize = [self size];
    float width = imageSize.width;
    float height = imageSize.height;
 
    float targetWidth = targetSize.width;
    float targetHeight = targetSize.height;
 
    // scaleFactor will be the fraction that we'll
    // use to adjust the size. For example, if we shrink
    // an image by half, scaleFactor will be 0.5. the
    // scaledWidth and scaledHeight will be the original,
    // multiplied by the scaleFactor.
    //
    // IMPORTANT: the "targetHeight" is the size of the space
    // we're drawing into. The "scaledHeight" is the height that
    // the image actually is drawn at, once we take into
    // account the idea of maintaining proportions
 
    float scaleFactor = 0.0;
    float scaledWidth = targetWidth;
    float scaledHeight = targetHeight;
 
    // since not all images are square, we want to scale
    // proportionately. To do this, we find the longest
    // edge and use that as a guide.
 
    if ( NSEqualSizes( imageSize, targetSize ) == NO )
    {
        // use the longeset edge as a guide. if the
        // image is wider than tall, we'll figure out
        // the scale factor by dividing it by the
        // intended width. Otherwise, we'll use the
        // height.
        
        float widthFactor;
        float heightFactor;
        
widthFactor = targetWidth / width;
heightFactor = targetHeight / height;
        
        if ( widthFactor < heightFactor )
            scaleFactor = widthFactor;
        else
            scaleFactor = heightFactor;
 
        // ex: 500 * 0.5 = 250 (newWidth)
        
        scaledWidth = width * scaleFactor;
        scaledHeight = height * scaleFactor;
    }
 
return NSMakeSize(scaledWidth,scaledHeight);
}
 
- (NSImage*)imageByScalingProportionallyToSize:(NSSize)targetSize
{
    return [self imageByScalingProportionallyToSize:targetSize
                                            flipped:NO];
}
 
- (NSImage*)imageByScalingProportionallyToSize:(NSSize)targetSize
                                       flipped:(BOOL)isFlipped
{
    return [self imageByScalingProportionallyToSize:targetSize
                                            flipped:isFlipped
                                           addFrame:NO
                                          addShadow:NO];
}
 
- (NSImage*)imageByScalingProportionallyToSize:(NSSize)targetSize
                                       flipped:(BOOL)isFlipped
                                      addFrame:(BOOL)shouldAddFrame
                                     addShadow:(BOOL)shouldAddShadow
{
    return [self imageByScalingProportionallyToSize:targetSize
                                            flipped:isFlipped
                                           addFrame:NO
                                          addShadow:NO
                                           addSheen:YES];
}
 
- (NSImage*)imageByScalingProportionallyToSize:(NSSize)targetSize
                                       flipped:(BOOL)isFlipped
                                      addFrame:(BOOL)shouldAddFrame
                                     addShadow:(BOOL)shouldAddShadow
                                      addSheen:(BOOL)shouldAddSheen
{
    NSImage* sourceImage = self;
 
NSImageRep* rep = [sourceImage bestRepresentationForDevice:nil];
NSInteger pixelsWide = [rep pixelsWide];
NSInteger pixelsHigh = [rep pixelsHigh];
[sourceImage setSize:NSMakeSize(pixelsWide,pixelsHigh)];
 
    NSImage* newImage = nil;
    if ([sourceImage isValid] == NO) return nil;
 
    // settings for shadow
    float shadowRadius = 4.0;
    NSSize shadowTargetSize = targetSize;
    if ( shouldAddShadow )
    {
        shadowTargetSize.width -= (shadowRadius * 2);
        shadowTargetSize.height -= (shadowRadius * 2);
    }
 
    NSSize imageSize = [sourceImage size];
    float width = imageSize.width;
    float height = imageSize.height;
 
    float targetWidth = targetSize.width;
    float targetHeight = targetSize.height;
 
    // scaleFactor will be the fraction that we'll
    // use to adjust the size. For example, if we shrink
    // an image by half, scaleFactor will be 0.5. the
    // scaledWidth and scaledHeight will be the original,
    // multiplied by the scaleFactor.
    //
    // IMPORTANT: the "targetHeight" is the size of the space
    // we're drawing into. The "scaledHeight" is the height that
    // the image actually is drawn at, once we take into
    // account the idea of maintaining proportions
 
    float scaleFactor = 0.0;
    float scaledWidth = targetWidth;
    float scaledHeight = targetHeight;
 
    NSPoint thumbnailPoint = NSMakePoint(0,0);
 
    // since not all images are square, we want to scale
    // proportionately. To do this, we find the longest
    // edge and use that as a guide.
 
    if ( NSEqualSizes( imageSize, targetSize ) == NO )
    {
        // use the longeset edge as a guide. if the
        // image is wider than tall, we'll figure out
        // the scale factor by dividing it by the
        // intended width. Otherwise, we'll use the
        // height.
        
        float widthFactor;
        float heightFactor;
        
        if ( shouldAddShadow ) {
            widthFactor = shadowTargetSize.width / width;
            heightFactor = shadowTargetSize.height / height;
        } else {
            widthFactor = targetWidth / width;
            heightFactor = targetHeight / height;
        }
        
        if ( widthFactor < heightFactor )
            scaleFactor = widthFactor;
        else
            scaleFactor = heightFactor;
 
        // ex: 500 * 0.5 = 250 (newWidth)
        
        scaledWidth = width * scaleFactor;
        scaledHeight = height * scaleFactor;
 
        // center the thumbnail in the frame. if
        // wider than tall, we need to adjust the
        // vertical drawing point (y axis)
        
        if ( widthFactor < heightFactor )
            thumbnailPoint.y = (targetHeight - scaledHeight) * 0.5;
 
        else if ( widthFactor > heightFactor )
            thumbnailPoint.x = (targetWidth - scaledWidth) * 0.5;
 
    }
 
    // create a new image to draw into
    newImage = [[NSImage alloc] initWithSize:targetSize];
    [newImage setCacheMode:NSImageCacheNever];
    [newImage setFlipped:isFlipped];
 
    // once focus is locked, all drawing goes into this NSImage instance
    // directly, not to the screen. It also receives its own graphics
    // context.
    //
    // Also, keep in mind that we're doing this in a background thread.
    // You only want to draw to the screen in the main thread, but
    // drawing to an offscreen image is (apparently) okay.
 
    [newImage lockFocus];
    
        [[NSGraphicsContext currentContext] setImageInterpolation:NSImageInterpolationHigh];
        
        // create the properly-scaled rect
        NSRect thumbnailRect;
        thumbnailRect.origin = thumbnailPoint;
        thumbnailRect.size.width = scaledWidth;
        thumbnailRect.size.height = scaledHeight;
        
        // add shadow below the image?
        if ( shouldAddShadow )
        {
            // we need to adjust the y coordinate to make sure
            // the image ends up in the right place in a flipped
            // coordinate system.
            if ( isFlipped && height > width )
                thumbnailRect.origin.y += (shadowRadius * 2);
            
            // draw the shadow where the image will be
            NSShadow* shadow = [[NSShadow alloc] init];
            [shadow setShadowColor:[NSColor colorWithCalibratedWhite:0.0 alpha:0.5]];
            if (isFlipped)
                [shadow setShadowOffset:NSMakeSize(shadowRadius,shadowRadius)];
            else
                [shadow setShadowOffset:NSMakeSize(shadowRadius,-shadowRadius)];
            [shadow setShadowBlurRadius:shadowRadius];
            [NSGraphicsContext saveGraphicsState];
                [shadow set];
                [[NSColor whiteColor] set];
                [NSBezierPath fillRect:thumbnailRect];
            [NSGraphicsContext restoreGraphicsState];
            [shadow release];
        }
            
        // draw the actual image
        [sourceImage drawInRect: thumbnailRect
                       fromRect: NSZeroRect
                      operation: NSCompositeSourceOver
                       fraction: 1.0];
        
        // add a frame above the image content?
        if ( shouldAddFrame )
        {
            // draw the larger internal frame
            NSRect insetFrameRect = NSInsetRect(thumbnailRect,3,3);
            NSBezierPath* insetFrame = [NSBezierPath bezierPathWithRect:insetFrameRect];
            [insetFrame setLineWidth:6.0];
            [[NSColor whiteColor] set];
            [insetFrame stroke];
 
            // draw the external bounding frame with no anti-aliasing
            [[NSColor colorWithCalibratedWhite:0.60 alpha:1.0] set];
            NSBezierPath* outsetFrame = [NSBezierPath bezierPathWithRect:thumbnailRect];
            [NSGraphicsContext saveGraphicsState];
                [[NSGraphicsContext currentContext] setShouldAntialias:NO];
                [outsetFrame setLineWidth:1.0];
                [outsetFrame stroke];
            [NSGraphicsContext restoreGraphicsState];
        }
 
if ( shouldAddSheen )
{
NSRect sheenRect = NSInsetRect(thumbnailRect,7,7);
CGFloat originalHeight = sheenRect.size.height;
sheenRect.size.height = originalHeight * 0.75;
sheenRect.origin.y += originalHeight * 0.25;
 
NSBezierPath* sheenPath = [NSBezierPath bezierPath];
NSPoint point1 = NSMakePoint ( sheenRect.origin.x + sheenRect.size.width, sheenRect.origin.y + sheenRect.size.height );
NSPoint point2 = NSMakePoint ( sheenRect.origin.x, sheenRect.origin.y + sheenRect.size.height );
NSPoint point3 = NSMakePoint ( sheenRect.origin.x, sheenRect.origin.y );
 
NSPoint controlPoint1 = point2;
NSPoint controlPoint2 = point1;
 
//[sheenPath moveToPoint:point1];
[sheenPath moveToPoint:point1];
[sheenPath lineToPoint:point2];
[sheenPath lineToPoint:point3];
[sheenPath curveToPoint:point1 controlPoint1:controlPoint1 controlPoint2:controlPoint2];
 
NSGradient* gradient = [[NSGradient alloc] initWithColorsAndLocations:
[NSColor colorWithCalibratedWhite:1.0 alpha:0.60], 0.00,
[NSColor colorWithCalibratedWhite:1.0 alpha:0.40], 0.15,
[NSColor colorWithCalibratedWhite:1.0 alpha:0.20], 0.28,
[NSColor colorWithCalibratedWhite:1.0 alpha:0.01], 0.85, nil];
 
[gradient drawInBezierPath:sheenPath angle:285.0];
[gradient release];
 
}
 
    [newImage unlockFocus];
    return [newImage autorelease];
}
 
@end
 
// from http://developer.apple.com/technotes/tn2005/tn2143.html
 
CGImageRef CreateCGImageFromData(NSData* data)
{
    CGImageRef imageRef = NULL;
    CGImageSourceRef sourceRef;
 
    sourceRef = CGImageSourceCreateWithData((CFDataRef)data, NULL);
    if(sourceRef) {
        imageRef = CGImageSourceCreateImageAtIndex(sourceRef, 0, NULL);
        CFRelease(sourceRef);
    }
 
    return imageRef;
}