jens@0
|
1 |
//
|
jens@0
|
2 |
// GraphicsUtils.m
|
jens@0
|
3 |
// MYUtilities
|
jens@0
|
4 |
//
|
jens@0
|
5 |
// Copyright 2008 Jens Alfke. All rights reserved.
|
jens@0
|
6 |
//
|
jens@0
|
7 |
|
jens@0
|
8 |
#import "GraphicsUtils.h"
|
jens@0
|
9 |
|
jens@0
|
10 |
|
jens@0
|
11 |
@implementation NSImage (MYUtilities)
|
jens@0
|
12 |
|
jens@0
|
13 |
|
jens@0
|
14 |
- (NSSize) my_sizeOfLargestRep
|
jens@0
|
15 |
{
|
jens@0
|
16 |
NSArray *reps = [self representations];
|
jens@0
|
17 |
NSSize max = {0,0};
|
jens@0
|
18 |
int i;
|
jens@0
|
19 |
for( i=[reps count]-1; i>=0; i-- ) {
|
jens@0
|
20 |
NSImageRep *rep = [reps objectAtIndex: i];
|
jens@0
|
21 |
NSSize size = [rep size];
|
jens@0
|
22 |
if( size.width > max.width || size.height > max.height ) {
|
jens@0
|
23 |
max = size;
|
jens@0
|
24 |
}
|
jens@0
|
25 |
}
|
jens@0
|
26 |
return max;
|
jens@0
|
27 |
}
|
jens@0
|
28 |
|
jens@0
|
29 |
|
jens@0
|
30 |
- (NSImage*) my_shrunkToFitIn: (NSSize) maxSize
|
jens@0
|
31 |
{
|
jens@0
|
32 |
NSSize size = self.size;
|
jens@0
|
33 |
float scale = MIN( size.width/maxSize.width, size.height/maxSize.height );
|
jens@0
|
34 |
if( scale >= 1.0 )
|
jens@0
|
35 |
return self;
|
jens@0
|
36 |
|
jens@0
|
37 |
NSSize newSize = {roundf(size.width*scale), roundf(size.height*scale)};
|
jens@0
|
38 |
NSImage *newImage = [[NSImage alloc] initWithSize: newSize];
|
jens@0
|
39 |
[newImage lockFocus];
|
jens@0
|
40 |
NSGraphicsContext *context = [NSGraphicsContext currentContext];
|
jens@0
|
41 |
[context saveGraphicsState];
|
jens@0
|
42 |
[context setImageInterpolation: NSImageInterpolationHigh];
|
jens@0
|
43 |
[self drawInRect: NSMakeRect(0,0,newSize.width,newSize.height)
|
jens@0
|
44 |
fromRect: NSMakeRect(0,0,size.width,size.height)
|
jens@0
|
45 |
operation: NSCompositeCopy fraction: 1.0f];
|
jens@0
|
46 |
[context restoreGraphicsState];
|
jens@0
|
47 |
[newImage unlockFocus];
|
jens@0
|
48 |
return [newImage autorelease];
|
jens@0
|
49 |
}
|
jens@0
|
50 |
|
jens@0
|
51 |
|
jens@0
|
52 |
- (NSData*) my_JPEGData
|
jens@0
|
53 |
{
|
jens@0
|
54 |
NSImage *tiffImage = [[NSImage alloc] initWithData:[self TIFFRepresentation]];
|
jens@0
|
55 |
NSBitmapImageRep *rep = [[tiffImage representations] objectAtIndex:0];
|
jens@0
|
56 |
NSDictionary *props = [NSDictionary dictionaryWithObjectsAndKeys:
|
jens@0
|
57 |
[NSNumber numberWithFloat: 0.75f], NSImageCompressionFactor, nil];
|
jens@0
|
58 |
NSData *jpeg = [rep representationUsingType: NSJPEGFileType properties: props];
|
jens@0
|
59 |
[tiffImage release];
|
jens@0
|
60 |
return jpeg;
|
jens@0
|
61 |
}
|
jens@0
|
62 |
|
jens@0
|
63 |
|
jens@0
|
64 |
#if 0
|
jens@0
|
65 |
|
jens@0
|
66 |
// Adapted from Apple's CocoaCreateMovie sample
|
jens@0
|
67 |
// <http://developer.apple.com/samplecode/Sample_Code/QuickTime/Basics/CocoaCreateMovie/MyController.m.htm>
|
jens@0
|
68 |
static void CopyNSImageRepToGWorld(NSBitmapImageRep *imageRepresentation, GWorldPtr gWorldPtr)
|
jens@0
|
69 |
{
|
jens@0
|
70 |
PixMapHandle pixMapHandle;
|
jens@0
|
71 |
unsigned char* pixBaseAddr;
|
jens@0
|
72 |
|
jens@0
|
73 |
// Lock the pixels
|
jens@0
|
74 |
pixMapHandle = GetGWorldPixMap(gWorldPtr);
|
jens@0
|
75 |
LockPixels (pixMapHandle);
|
jens@0
|
76 |
pixBaseAddr = (unsigned char*) GetPixBaseAddr(pixMapHandle);
|
jens@0
|
77 |
|
jens@0
|
78 |
const unsigned char* bitMapDataPtr = [imageRepresentation bitmapData];
|
jens@0
|
79 |
|
jens@0
|
80 |
if ((bitMapDataPtr != nil) && (pixBaseAddr != nil))
|
jens@0
|
81 |
{
|
jens@0
|
82 |
int i,j;
|
jens@0
|
83 |
int pixmapRowBytes = GetPixRowBytes(pixMapHandle);
|
jens@0
|
84 |
NSSize imageSize = [imageRepresentation size];
|
jens@0
|
85 |
for (i=0; i< imageSize.height; i++)
|
jens@0
|
86 |
{
|
jens@0
|
87 |
const unsigned char *src = bitMapDataPtr + i * [imageRepresentation bytesPerRow];
|
jens@0
|
88 |
unsigned char *dst = pixBaseAddr + i * pixmapRowBytes;
|
jens@0
|
89 |
for (j = 0; j < imageSize.width; j++)
|
jens@0
|
90 |
{
|
jens@0
|
91 |
*dst++ = 0; // X - our src is 24-bit only
|
jens@0
|
92 |
*dst++ = *src++; // Red component
|
jens@0
|
93 |
*dst++ = *src++; // Green component
|
jens@0
|
94 |
*dst++ = *src++; // Blue component
|
jens@0
|
95 |
}
|
jens@0
|
96 |
}
|
jens@0
|
97 |
}
|
jens@0
|
98 |
UnlockPixels(pixMapHandle);
|
jens@0
|
99 |
}
|
jens@0
|
100 |
|
jens@0
|
101 |
|
jens@0
|
102 |
- (NSData*) my_PICTData
|
jens@0
|
103 |
{
|
jens@0
|
104 |
// Locate the bitmap image rep:
|
jens@0
|
105 |
NSBitmapImageRep *rep;
|
jens@0
|
106 |
NSEnumerator *e = [[self representations] objectEnumerator];
|
jens@0
|
107 |
while( (rep=[e nextObject]) != nil ) {
|
jens@0
|
108 |
if( [rep isKindOfClass: [NSBitmapImageRep class]] )
|
jens@0
|
109 |
break;
|
jens@0
|
110 |
}
|
jens@0
|
111 |
if( ! rep ) {
|
jens@0
|
112 |
Warn(@"No bitmap image rep in image");
|
jens@0
|
113 |
return nil;
|
jens@0
|
114 |
}
|
jens@0
|
115 |
|
jens@0
|
116 |
// Copy the image data into a GWorld:
|
jens@0
|
117 |
Rect bounds;
|
jens@0
|
118 |
SetRect(&bounds, 0,0,[rep pixelsWide],[rep pixelsHigh]);
|
jens@0
|
119 |
GWorldPtr gworld;
|
jens@0
|
120 |
OSStatus err = NewGWorld(&gworld, 32, &bounds, NULL, NULL, 0);
|
jens@0
|
121 |
if( err ) {
|
jens@0
|
122 |
Warn(@"NewGWorld failed with err %i",err);
|
jens@0
|
123 |
return nil;
|
jens@0
|
124 |
}
|
jens@0
|
125 |
CopyNSImageRepToGWorld(rep,gworld);
|
jens@0
|
126 |
|
jens@0
|
127 |
// Draw the GWorld into a PicHandle:
|
jens@0
|
128 |
CGrafPtr oldPort;
|
jens@0
|
129 |
GDHandle oldDevice;
|
jens@0
|
130 |
GetGWorld(&oldPort,&oldDevice);
|
jens@0
|
131 |
SetGWorld(gworld,NULL);
|
jens@0
|
132 |
ClipRect(&bounds);
|
jens@0
|
133 |
PicHandle pic = OpenPicture(&bounds);
|
jens@0
|
134 |
CopyBits(GetPortBitMapForCopyBits(gworld),
|
jens@0
|
135 |
GetPortBitMapForCopyBits(gworld),
|
jens@0
|
136 |
&bounds,&bounds,srcCopy,NULL);
|
jens@0
|
137 |
ClosePicture();
|
jens@0
|
138 |
err = QDError();
|
jens@0
|
139 |
SetGWorld(oldPort,oldDevice);
|
jens@0
|
140 |
DisposeGWorld(gworld);
|
jens@0
|
141 |
|
jens@0
|
142 |
if( err ) {
|
jens@0
|
143 |
Warn(@"Couldn't convert to PICT: error %i",err);
|
jens@0
|
144 |
return nil;
|
jens@0
|
145 |
}
|
jens@0
|
146 |
|
jens@0
|
147 |
// Copy the PicHandle into an NSData:
|
jens@0
|
148 |
HLock((Handle)pic);
|
jens@0
|
149 |
//Test to put PICT on clipboard:
|
jens@0
|
150 |
/*ScrapRef scrap;
|
jens@0
|
151 |
GetCurrentScrap(&scrap);
|
jens@0
|
152 |
ClearScrap(&scrap);
|
jens@0
|
153 |
PutScrapFlavor(scrap,'PICT',0,GetHandleSize((Handle)pic),*pic);*/
|
jens@0
|
154 |
NSData *data = [NSData dataWithBytes: *pic length: GetHandleSize((Handle)pic)];
|
jens@0
|
155 |
DisposeHandle((Handle)pic);
|
jens@0
|
156 |
Log(@"Converted image to %i bytes of PICT data",[data length]);
|
jens@0
|
157 |
return data;
|
jens@0
|
158 |
}
|
jens@0
|
159 |
#endif
|
jens@0
|
160 |
|
jens@0
|
161 |
|
jens@0
|
162 |
@end
|
jens@0
|
163 |
|
jens@0
|
164 |
|
jens@0
|
165 |
|
jens@0
|
166 |
|
jens@0
|
167 |
@implementation NSBezierPath (MYUtilities)
|
jens@0
|
168 |
|
jens@0
|
169 |
+ (NSBezierPath*) my_bezierPathWithRoundRect: (NSRect)rect radius: (float)radius
|
jens@0
|
170 |
{
|
jens@0
|
171 |
radius = MIN(radius, floorf(rect.size.width/2));
|
jens@0
|
172 |
float x0 = NSMinX(rect), y0 = NSMinY(rect),
|
jens@0
|
173 |
x1 = NSMaxX(rect), y1 = NSMaxY(rect);
|
jens@0
|
174 |
NSBezierPath *path = [NSBezierPath bezierPath];
|
jens@0
|
175 |
|
jens@0
|
176 |
[path moveToPoint: NSMakePoint(x0+radius,y0)];
|
jens@0
|
177 |
|
jens@0
|
178 |
[path appendBezierPathWithArcFromPoint: NSMakePoint(x1,y0)
|
jens@0
|
179 |
toPoint: NSMakePoint(x1,y1) radius: radius];
|
jens@0
|
180 |
[path appendBezierPathWithArcFromPoint: NSMakePoint(x1,y1)
|
jens@0
|
181 |
toPoint: NSMakePoint(x0,y1) radius: radius];
|
jens@0
|
182 |
[path appendBezierPathWithArcFromPoint: NSMakePoint(x0,y1)
|
jens@0
|
183 |
toPoint: NSMakePoint(x0,y0) radius: radius];
|
jens@0
|
184 |
[path appendBezierPathWithArcFromPoint: NSMakePoint(x0,y0)
|
jens@0
|
185 |
toPoint: NSMakePoint(x1,y0) radius: radius];
|
jens@0
|
186 |
[path closePath];
|
jens@0
|
187 |
return path;
|
jens@0
|
188 |
}
|
jens@0
|
189 |
|
jens@0
|
190 |
@end
|