Reputation: 3809
I'm trying to do the following batch processing:
So far, I came up with this:
CGPoint center = CGPointMake(self.window.frame.size.width / 2., self.window.frame.size.height / 2.);
[[NSGraphicsContext currentContext] setImageInterpolation:NSImageInterpolationHigh];
NSImage * newThumbnail = [[NSImage alloc] initWithData:[NSData dataWithContentsOfURL:[files objectAtIndex:0]]];
NSImageView *imageView = [[NSImageView alloc] initWithFrame:CGRectMake(center.x - (57/2.), center.y - (80/2.), 57, 80)];
[imageView setWantsLayer:YES];
imageView.layer.borderColor = [[NSColor blackColor] CGColor];
imageView.layer.cornerRadius = 4;
imageView.layer.masksToBounds = YES;
imageView.layer.borderWidth = 1.0;
imageView.image = newThumbnail;
And now I think I'm missing telling the layer to redender to some context?
maybe something like [imageView.layer drawInContext: some context (NS o CG?)];
and saving that context to disk. But I'm confused as to:
what context,
whether to go from context to NSData to disk,
or if I need an intermediate image somewhere before saving.
Basically, between CALayers and CGLayers and NS objects and UI objects (I know I'm in OS X Cocoa here and it's no UIKit and I'm also not using CG stuff so far) I have no idea how to turn the above into a png.
Upvotes: 1
Views: 1168
Reputation: 46020
You shouldn't be using a view at all, since you're not needing to display to screen. You should be using an offscreen bitmap (an NSBitmapImageRep
) and using drawing commands to draw the image.
You have two choices with drawing in Cocoa. The easiest way is to use the various Cocoa drawing classes such as NSBezierPath
and friends. The other option is the more powerful but also more low-level and complex Quartz APIs, which are not object-oriented but use a C function syntax.
Here is an example of how to do what you want using Cocoa drawing:
NSImage* anImage = [NSImage imageNamed:@"Lenna.tiff"]; //or some other source
//create a bitmap at a specific size
NSRect offscreenRect = NSMakeRect(0.0, 0.0, 250.0, 250.0);
NSBitmapImageRep* bitmap = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:nil
pixelsWide:offscreenRect.size.width
pixelsHigh:offscreenRect.size.height
bitsPerSample:8
samplesPerPixel:4
hasAlpha:YES
isPlanar:NO
colorSpaceName:NSCalibratedRGBColorSpace
bitmapFormat:0
bytesPerRow:(4 * offscreenRect.size.width)
bitsPerPixel:32];
//save the current graphics context and lock focus on the bitmap
NSGraphicsContext* originalContext = [NSGraphicsContext currentContext];
[NSGraphicsContext setCurrentContext:[NSGraphicsContext
graphicsContextWithBitmapImageRep:bitmap]];
[NSGraphicsContext saveGraphicsState];
//clear the image rep. This is faster than filling with [NSColor clearColor].
unsigned char *bitmapData = [bitmap bitmapData];
if (bitmapData)
bzero(bitmapData, [bitmap bytesPerRow] * [bitmap pixelsHigh]);
//create the border path
CGFloat borderWidth = 2.0;
CGFloat cornerRadius = 14.0;
NSRect borderRect = NSInsetRect(offscreenRect, borderWidth/2.0, borderWidth/2.0);
NSBezierPath* border = [NSBezierPath bezierPathWithRoundedRect:borderRect xRadius:cornerRadius yRadius:cornerRadius];
[border setLineWidth:borderWidth];
//set the border as a clipping path
[NSGraphicsContext saveGraphicsState];
[border addClip];
//scale and draw the image
[anImage setSize:offscreenRect.size];
[anImage drawAtPoint:NSZeroPoint fromRect:NSZeroRect operation:NSCompositeSourceOver fraction:1.0];
[NSGraphicsContext restoreGraphicsState];
//set the border color
[[NSColor blackColor] set];
//draw the border
[border stroke];
//restore the original graphics context
[NSGraphicsContext restoreGraphicsState];
[NSGraphicsContext setCurrentContext:originalContext];
//get PNG data from the image rep
NSData* pngData = [bitmap representationUsingType:NSPNGFileType properties:nil];
NSError* error;
if(![pngData writeToURL:[NSURL fileURLWithPath:[NSHomeDirectory() stringByAppendingPathComponent:@"test.png"]] options:NSDataWritingAtomic error:&error])
{
NSLog(@"%@",error);
}
Upvotes: 2