How do I draw NSGradient to NSImage?

1.2k Views Asked by At

I'm trying to take an NSGradient and save it as an image in RubyMotion, but I can't get it to work. This is the code I have so far:

gradient = NSGradient.alloc.initWithColors(colors, 
  atLocations: locations.to_pointer(:double), 
  colorSpace: NSColorSpace.genericRGBColorSpace
)

size = Size(width, height)
image = NSImage.imageWithSize(size, flipped: false, drawingHandler: lambda do |rect|
  gradient.drawInRect(rect, angle: angle)
  true
end)

data = image.TIFFRepresentation
data.writeToFile('output.tif', atomically: false)

It runs without error, but the file that is saved is blank and there is no image data. Can anyone help point me in the right direction?

2

There are 2 best solutions below

1
On BEST ANSWER

I don’t know about RubyMotion, but here’s how to do it in Objective-C:

NSGradient *grad = [[NSGradient alloc] initWithStartingColor:[NSColor redColor]
                                                 endingColor:[NSColor blueColor]];

NSRect rect = CGRectMake(0.0, 0.0, 50.0, 50.0);
NSImage *image = [[NSImage alloc] initWithSize:rect.size];
NSBezierPath *path = [NSBezierPath bezierPathWithRect:rect];
[image lockFocus];
[grad drawInBezierPath:path angle:0.0];
NSBitmapImageRep *imgRep = [[NSBitmapImageRep alloc] initWithFocusedViewRect:rect];
NSData *data = [imgRep representationUsingType:NSPNGFileType properties:nil];
[image unlockFocus];
[data writeToFile: @"/path/to/file.png" atomically:NO];
0
On

In case you want to know how it works in Swift 5:

extension NSImage {
    convenience init?(gradientColors: [NSColor], imageSize: NSSize) {
        guard let gradient = NSGradient(colors: gradientColors) else { return nil }
        let rect = NSRect(origin: CGPoint.zero, size: imageSize)
        self.init(size: rect.size)
        let path = NSBezierPath(rect: rect)
        self.lockFocus()
        gradient.draw(in: path, angle: 0.0)
        self.unlockFocus()
    }
}