Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C#

Drawing into bitmaps and saving as a PNG in Swift on OS X

4.00/5 (1 vote)
4 May 2015CPOL1 min read 16K  
Drawing into bitmaps and saving as a PNG in Swift on OS X

Not an in depth post today. For small iOS Swift/SpriteKit game I'm writing for fun, I wanted a very basic grass sprite that could be scrolled; to create a parallax effect. This amounts to a 800x400 bitmap which contains sequential isosceles triangles of 40 pixels with random heights (of up to 400 pixels) and coloured using a lawn green colour.

Initially, I was creating an SKShapeNode and creating the triangles above but when scrolling the redrawing of these hurt performance, especially when running on the iOS Simulator hence the desire to use a sprite.

I had a go at creating these with Photoshop. Whilst switching to a sprite improved performance the look of the triangles drawn by hand wasn't as good as the randomly generated ones. Therefore, I thought I'd generate the sprite.

It wasn't really practical to do this on iOS as the file was needed in Xcode so I thought I'd try experimenting with a command line OS X (Cocoa) program in Swift. A GUI would possibly be nice to preview the results (and re-generate if needed) and to select the save-to file location but this solution sufficed.

I'd not done any non-iOS Swift development and never generated PNGs so various amounts of Googling and StackOverflow-ing was needed. Whilst the results of these searches were very helpful, I didn't come across anything showing a complete program to create a bitmap, draw into it and then save so the finished program is presented below. It's also available as a gist.

1:  import Cocoa  
2:    
3:  private func saveAsPNGWithName(fileName: String, bitMap: NSBitmapImageRep) -> Bool  
4:  {  
5:      let props: [NSObject:AnyObject] = [:]  
6:      let imageData = bitMap.representationUsingType(NSBitmapImageFileType.NSPNGFileType, properties: props)  
7:        
8:      let myPath = NSFileManager.defaultManager().currentDirectoryPath  
9:        
10:      return imageData!.writeToFile(fileName, atomically: false)  
11:  }  
12:    
13:  private func drawGrassIntoBitmap(bitmap: NSBitmapImageRep)  
14:  {  
15:      var ctx = NSGraphicsContext(bitmapImageRep: bitmap)  
16:        
17:      NSGraphicsContext.setCurrentContext(ctx)  
18:        
19:      NSColor(red: 124 / 255, green: 252 / 255, blue: 0, alpha: 1.0).set()  
20:        
21:      let path = NSBezierPath()  
22:        
23:      path.moveToPoint(NSPoint(x: 0, y: 0))  
24:        
25:      for i in stride(from: 0, through: SIZE.width, by: 40)  
26:      {  
27:          path.lineToPoint(NSPoint(x: CGFloat(i + 20), y: CGFloat(arc4random_uniform(400))))  
28:          path.lineToPoint(NSPoint(x: i + 40, y: 0))  
29:      }  
30:        
31:      path.stroke()  
32:      path.fill()  
33:        
34:  }  
35:    
36:  let SIZE = CGSize(width: 800, height: 400)  
37:    
38:  println("\(Process.arguments[0])")  
39:    
40:  if Process.arguments.count != 2  
41:  {  
42:      println("usage: grass <file>")  
43:      exit(1)  
44:  }  
45:    
46:  let grass = NSBitmapImageRep(bitmapDataPlanes: nil, pixelsWide: Int(SIZE.width), 
pixelsHigh: Int(SIZE.height), bitsPerSample: 8, samplesPerPixel: 4, hasAlpha: true, 
isPlanar: false, colorSpaceName: NSDeviceRGBColorSpace, bytesPerRow: 0, bitsPerPixel: 0)  
47:        
48:  drawGrassIntoBitmap(grass!)  
49:  saveAsPNGWithName(Process.arguments[1], grass!)  
50: 

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)